diff --git a/Source/control.cpp b/Source/control.cpp index 6a104ac49..cd5c91932 100644 --- a/Source/control.cpp +++ b/Source/control.cpp @@ -122,11 +122,11 @@ namespace { std::optional pLifeBuff; std::optional pManaBuff; -std::optional talkButtons; -std::optional pDurIcons; -std::optional multiButtons; -std::optional pPanelButtons; -std::optional pGBoxBuff; +std::optional talkButtons; +std::optional pDurIcons; +std::optional multiButtons; +std::optional pPanelButtons; +std::optional pGBoxBuff; bool PanelButtons[8]; int PanelButtonIndex; @@ -518,7 +518,7 @@ void InitControlPan() CelDrawUnsafeTo(*pBtmBuff, { 0, (PANEL_HEIGHT + 16) - 1 }, LoadCel("CtrlPan\\Panel8.CEL", PANEL_WIDTH), 1); { const Point bulbsPosition { 0, 87 }; - const CelSprite statusPanel = LoadCel("CtrlPan\\P8Bulbs.CEL", 88); + const OwnedCelSprite statusPanel = LoadCel("CtrlPan\\P8Bulbs.CEL", 88); CelDrawUnsafeTo(*pLifeBuff, bulbsPosition, statusPanel, 1); CelDrawUnsafeTo(*pManaBuff, bulbsPosition, statusPanel, 2); } diff --git a/Source/controls/modifier_hints.cpp b/Source/controls/modifier_hints.cpp index 8b11210e4..ee0d1a43e 100644 --- a/Source/controls/modifier_hints.cpp +++ b/Source/controls/modifier_hints.cpp @@ -15,7 +15,7 @@ namespace devilution { -extern std::optional pSBkIconCels; +extern std::optional pSBkIconCels; namespace { diff --git a/Source/controls/touch/renderers.cpp b/Source/controls/touch/renderers.cpp index 00afb205f..9e98802e5 100644 --- a/Source/controls/touch/renderers.cpp +++ b/Source/controls/touch/renderers.cpp @@ -139,7 +139,7 @@ void LoadPotionArt(Art *potionArt, SDL_Renderer *renderer) Point position { 0, 0 }; for (item_cursor_graphic graphic : potionGraphics) { const int frame = CURSOR_FIRSTITEM + graphic; - const CelSprite &potionSprite = GetInvItemSprite(frame); + const OwnedCelSprite &potionSprite = GetInvItemSprite(frame); position.y += potionSize.height; CelClippedDrawTo(Surface(surface.get()), position, potionSprite, frame); } diff --git a/Source/cursor.cpp b/Source/cursor.cpp index 2ad9d45ad..8deb50107 100644 --- a/Source/cursor.cpp +++ b/Source/cursor.cpp @@ -27,8 +27,8 @@ namespace devilution { namespace { /** Cursor images CEL */ -std::optional pCursCels; -std::optional pCursCels2; +std::optional pCursCels; +std::optional pCursCels2; constexpr int InvItems1Size = 180; /** Maps from objcurs.cel frame number to frame width. */ @@ -143,7 +143,7 @@ void FreeCursor() ClearCursor(); } -const CelSprite &GetInvItemSprite(int i) +const OwnedCelSprite &GetInvItemSprite(int i) { return i < InvItems1Size ? *pCursCels : *pCursCels2; } diff --git a/Source/cursor.h b/Source/cursor.h index 9e3692c8a..f43142342 100644 --- a/Source/cursor.h +++ b/Source/cursor.h @@ -61,7 +61,7 @@ inline bool IsItemSprite(int cursId) void CelDrawCursor(const Surface &out, Point position, int cursId); /** Returns the sprite for the given inventory index. */ -const CelSprite &GetInvItemSprite(int i); +const OwnedCelSprite &GetInvItemSprite(int i); /** Returns the CEL frame index for the given inventory index. */ int GetInvItemFrame(int i); diff --git a/Source/dead.cpp b/Source/dead.cpp index 022b09a65..d71d95a21 100644 --- a/Source/dead.cpp +++ b/Source/dead.cpp @@ -18,12 +18,10 @@ int8_t stonendx; namespace { void InitDeadAnimationFromMonster(Corpse &corpse, const CMonster &mon) { - int i = 0; const auto &animData = mon.GetAnimData(MonsterGraphic::Death); - for (const auto &celSprite : animData.CelSpritesForDirections) - corpse.data[i++] = celSprite->Data(); + memcpy(&corpse.data[0], &animData.CelSpritesForDirections[0], sizeof(animData.CelSpritesForDirections[0]) * animData.CelSpritesForDirections.size()); corpse.frame = animData.Frames; - corpse.width = animData.CelSpritesForDirections[0]->Width(); + corpse.width = animData.Width; } } // namespace diff --git a/Source/dead.h b/Source/dead.h index 123c1efb1..c9bb08bfe 100644 --- a/Source/dead.h +++ b/Source/dead.h @@ -18,7 +18,7 @@ static constexpr unsigned MaxCorpses = 31; struct Corpse { std::array data; int frame; - int width; + unsigned width; uint8_t translationPaletteIndex; }; diff --git a/Source/debug.cpp b/Source/debug.cpp index 5a072f2b6..91587940b 100644 --- a/Source/debug.cpp +++ b/Source/debug.cpp @@ -32,7 +32,7 @@ namespace devilution { -std::optional pSquareCel; +std::optional pSquareCel; bool DebugToggle = false; bool DebugGodMode = false; bool DebugVision = false; diff --git a/Source/debug.h b/Source/debug.h index bd4060ea9..0f2f6cd2a 100644 --- a/Source/debug.h +++ b/Source/debug.h @@ -15,7 +15,7 @@ namespace devilution { -extern std::optional pSquareCel; +extern std::optional pSquareCel; extern bool DebugToggle; extern bool DebugGodMode; extern bool DebugVision; diff --git a/Source/doom.cpp b/Source/doom.cpp index b5caa41be..1ce4118b8 100644 --- a/Source/doom.cpp +++ b/Source/doom.cpp @@ -14,7 +14,7 @@ namespace devilution { namespace { -std::optional DoomCel; +std::optional DoomCel; } // namespace bool DoomFlag; diff --git a/Source/engine/animationinfo.cpp b/Source/engine/animationinfo.cpp index 463825d7e..1356e43e3 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*/, float previewShownGameTickFragments /*= 0.F*/) +void AnimationInfo::SetNewAnimation(std::optional 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. @@ -90,7 +90,7 @@ void AnimationInfo::SetNewAnimation(const CelSprite *celSprite, int numberOfFram ticksPerFrame = 1; } - this->pCelSprite = celSprite; + this->celSprite = celSprite; NumberOfFrames = numberOfFrames; CurrentFrame = 1 + numSkippedFrames; TickCounterOfCurrentFrame = 0; @@ -168,7 +168,7 @@ void AnimationInfo::SetNewAnimation(const CelSprite *celSprite, int numberOfFram } } -void AnimationInfo::ChangeAnimationData(const CelSprite *celSprite, int numberOfFrames, int ticksPerFrame) +void AnimationInfo::ChangeAnimationData(std::optional celSprite, int numberOfFrames, int 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 @@ -183,7 +183,7 @@ void AnimationInfo::ChangeAnimationData(const CelSprite *celSprite, int numberOf RelevantFramesForDistributing = 0; TickModifier = 0.0F; } - this->pCelSprite = celSprite; + this->celSprite = celSprite; } void AnimationInfo::ProcessAnimation(bool reverseAnimation /*= false*/, bool dontProgressAnimation /*= false*/) diff --git a/Source/engine/animationinfo.h b/Source/engine/animationinfo.h index fb3ea1a28..770a636be 100644 --- a/Source/engine/animationinfo.h +++ b/Source/engine/animationinfo.h @@ -5,10 +5,11 @@ */ #pragma once -#include +#include #include #include "engine/cel_sprite.hpp" +#include "utils/stdcompat/optional.hpp" namespace devilution { @@ -37,9 +38,9 @@ enum AnimationDistributionFlags : uint8_t { class AnimationInfo { public: /** - * @brief Pointer to Animation Sprite + * @brief Animation sprite */ - const CelSprite *pCelSprite; + std::optional celSprite; /** * @brief How many game ticks are needed to advance one Animation Frame */ @@ -82,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(const 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, 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. @@ -90,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(const CelSprite *celSprite, int numberOfFrames, int ticksPerFrame); + void ChangeAnimationData(std::optional celSprite, int numberOfFrames, int ticksPerFrame); /** * @brief Process the Animation for a game tick (for example advances the frame) diff --git a/Source/engine/cel_sprite.hpp b/Source/engine/cel_sprite.hpp index 96fa12a61..c9fcfd95c 100644 --- a/Source/engine/cel_sprite.hpp +++ b/Source/engine/cel_sprite.hpp @@ -7,39 +7,31 @@ namespace devilution { +class OwnedCelSprite; + /** * Stores a CEL or CL2 sprite and its width(s). - * - * The data may be unowned. - * Eventually we'd like to remove the unowned version. + * Does not own the data. */ class CelSprite { public: - CelSprite(std::unique_ptr data, int width) - : data_(std::move(data)) - , data_ptr_(data_.get()) + CelSprite(const byte *data, int width) + : data_ptr_(data) , width_(width) { } - CelSprite(std::unique_ptr data, const int *widths) - : data_(std::move(data)) - , data_ptr_(data_.get()) + CelSprite(const byte *data, const int *widths) + : data_ptr_(data) , widths_(widths) { } - /** - * Constructs an unowned sprite. - * Ideally we'd like to remove all uses of this constructor. - */ - CelSprite(const byte *data, int width) - : data_ptr_(data) - , width_(width) - { - } + explicit CelSprite(const OwnedCelSprite &owned); + CelSprite(const CelSprite &) = default; CelSprite(CelSprite &&) noexcept = default; + CelSprite &operator=(const CelSprite &) = default; CelSprite &operator=(CelSprite &&) noexcept = default; [[nodiscard]] const byte *Data() const @@ -52,11 +44,54 @@ public: return widths_ == nullptr ? width_ : widths_[frame]; } + [[nodiscard]] bool operator==(CelSprite other) const + { + return data_ptr_ == other.data_ptr_; + } + [[nodiscard]] bool operator!=(CelSprite other) const + { + return data_ptr_ != other.data_ptr_; + } + private: - std::unique_ptr data_; const byte *data_ptr_; int width_ = 0; const int *widths_ = nullptr; // unowned }; +/** + * Stores a CEL or CL2 sprite and its width(s). + * Owns the data. + */ +class OwnedCelSprite : public CelSprite { +public: + OwnedCelSprite(std::unique_ptr data, int width) + : CelSprite(data.get(), width) + , data_(std::move(data)) + { + } + + OwnedCelSprite(std::unique_ptr data, const int *widths) + : CelSprite(data.get(), widths) + , data_(std::move(data)) + { + } + + OwnedCelSprite(OwnedCelSprite &&) noexcept = default; + OwnedCelSprite &operator=(OwnedCelSprite &&) noexcept = default; + + [[nodiscard]] CelSprite Unowned() const + { + return CelSprite(*this); + } + +private: + std::unique_ptr data_; +}; + +inline CelSprite::CelSprite(const OwnedCelSprite &owned) + : CelSprite(static_cast(owned)) +{ +} + } // namespace devilution diff --git a/Source/engine/load_cel.cpp b/Source/engine/load_cel.cpp index 93220eed6..0391fecc2 100644 --- a/Source/engine/load_cel.cpp +++ b/Source/engine/load_cel.cpp @@ -4,14 +4,14 @@ namespace devilution { -CelSprite LoadCel(const char *pszName, int width) +OwnedCelSprite LoadCel(const char *pszName, int width) { - return CelSprite(LoadFileInMem(pszName), width); + return OwnedCelSprite(LoadFileInMem(pszName), width); } -CelSprite LoadCel(const char *pszName, const int *widths) +OwnedCelSprite LoadCel(const char *pszName, const int *widths) { - return CelSprite(LoadFileInMem(pszName), widths); + return OwnedCelSprite(LoadFileInMem(pszName), widths); } } // namespace devilution diff --git a/Source/engine/load_cel.hpp b/Source/engine/load_cel.hpp index 545ae2533..7c8c7056a 100644 --- a/Source/engine/load_cel.hpp +++ b/Source/engine/load_cel.hpp @@ -7,7 +7,7 @@ namespace devilution { /** * @brief Loads a Cel sprite and sets its width */ -CelSprite LoadCel(const char *pszName, int width); -CelSprite LoadCel(const char *pszName, const int *widths); +OwnedCelSprite LoadCel(const char *pszName, int width); +OwnedCelSprite LoadCel(const char *pszName, const int *widths); } // namespace devilution diff --git a/Source/engine/render/cel_render.cpp b/Source/engine/render/cel_render.cpp index 63932db2d..3bd2584ba 100644 --- a/Source/engine/render/cel_render.cpp +++ b/Source/engine/render/cel_render.cpp @@ -580,14 +580,14 @@ void CelBlitLightSafeTo(const Surface &out, Point position, const byte *pRLEByte } // namespace -void CelDrawTo(const Surface &out, Point position, const CelSprite &cel, int frame) +void CelDrawTo(const Surface &out, Point position, CelSprite cel, int frame) { int nDataSize; const auto *pRLEBytes = CelGetFrame(cel.Data(), frame, &nDataSize); CelBlitSafeTo(out, position, pRLEBytes, nDataSize, cel.Width(frame)); } -void CelClippedDrawTo(const Surface &out, Point position, const CelSprite &cel, int frame) +void CelClippedDrawTo(const Surface &out, Point position, CelSprite cel, int frame) { int nDataSize; const auto *pRLEBytes = CelGetFrameClipped(cel.Data(), frame, &nDataSize); @@ -595,7 +595,7 @@ void CelClippedDrawTo(const Surface &out, Point position, const CelSprite &cel, CelBlitSafeTo(out, position, pRLEBytes, nDataSize, cel.Width(frame)); } -void CelDrawLightTo(const Surface &out, Point position, const CelSprite &cel, int frame, uint8_t *tbl) +void CelDrawLightTo(const Surface &out, Point position, CelSprite cel, int frame, uint8_t *tbl) { int nDataSize; const auto *pRLEBytes = CelGetFrame(cel.Data(), frame, &nDataSize); @@ -606,7 +606,7 @@ void CelDrawLightTo(const Surface &out, Point position, const CelSprite &cel, in CelBlitSafeTo(out, position, pRLEBytes, nDataSize, cel.Width(frame)); } -void CelClippedDrawLightTo(const Surface &out, Point position, const CelSprite &cel, int frame) +void CelClippedDrawLightTo(const Surface &out, Point position, CelSprite cel, int frame) { int nDataSize; const auto *pRLEBytes = CelGetFrameClipped(cel.Data(), frame, &nDataSize); @@ -617,14 +617,14 @@ void CelClippedDrawLightTo(const Surface &out, Point position, const CelSprite & CelBlitSafeTo(out, position, pRLEBytes, nDataSize, cel.Width(frame)); } -void CelDrawLightRedTo(const Surface &out, Point position, const CelSprite &cel, int frame) +void CelDrawLightRedTo(const Surface &out, Point position, CelSprite cel, int frame) { int nDataSize; const auto *pRLEBytes = CelGetFrameClipped(cel.Data(), frame, &nDataSize); RenderCelWithLightTable(out, position, pRLEBytes, nDataSize, cel.Width(frame), GetInfravisionTRN()); } -void CelDrawItem(const Item &item, const Surface &out, Point position, const CelSprite &cel, int frame) +void CelDrawItem(const Item &item, const Surface &out, Point position, CelSprite cel, int frame) { bool usable = item._iStatFlag; if (!usable) { @@ -634,7 +634,7 @@ void CelDrawItem(const Item &item, const Surface &out, Point position, const Cel } } -void CelClippedBlitLightTransTo(const Surface &out, Point position, const CelSprite &cel, int frame) +void CelClippedBlitLightTransTo(const Surface &out, Point position, CelSprite cel, int frame) { int nDataSize; const byte *pRLEBytes = CelGetFrameClipped(cel.Data(), frame, &nDataSize); @@ -647,14 +647,14 @@ void CelClippedBlitLightTransTo(const Surface &out, Point position, const CelSpr CelBlitSafeTo(out, position, pRLEBytes, nDataSize, cel.Width(frame)); } -void CelDrawUnsafeTo(const Surface &out, Point position, const CelSprite &cel, int frame) +void CelDrawUnsafeTo(const Surface &out, Point position, CelSprite cel, int frame) { int nDataSize; const auto *pRLEBytes = CelGetFrame(cel.Data(), frame, &nDataSize); RenderCelClipY(out, position, pRLEBytes, nDataSize, cel.Width(frame), RenderLineMemcpy, NullLineEndFn); } -void CelBlitOutlineTo(const Surface &out, uint8_t col, Point position, const CelSprite &cel, int frame, bool skipColorIndexZero) +void CelBlitOutlineTo(const Surface &out, uint8_t col, Point position, CelSprite cel, int frame, bool skipColorIndexZero) { int nDataSize; const byte *src = CelGetFrameClipped(cel.Data(), frame, &nDataSize); @@ -664,7 +664,7 @@ void CelBlitOutlineTo(const Surface &out, uint8_t col, Point position, const Cel RenderCelOutline(out, position, src, nDataSize, cel.Width(frame), col); } -std::pair MeasureSolidHorizontalBounds(const CelSprite &cel, int frame) +std::pair MeasureSolidHorizontalBounds(CelSprite cel, int frame) { int nDataSize; const byte *src = CelGetFrameClipped(cel.Data(), frame, &nDataSize); diff --git a/Source/engine/render/cel_render.hpp b/Source/engine/render/cel_render.hpp index 23661901e..db6c1659c 100644 --- a/Source/engine/render/cel_render.hpp +++ b/Source/engine/render/cel_render.hpp @@ -18,7 +18,7 @@ namespace devilution { * Returns a pair of X coordinates containing the start (inclusive) and end (exclusive) * of fully transparent columns in the sprite. */ -std::pair MeasureSolidHorizontalBounds(const CelSprite &cel, int frame = 1); +std::pair MeasureSolidHorizontalBounds(CelSprite cel, int frame = 1); /** * @brief Blit CEL sprite to the back buffer at the given coordinates @@ -27,7 +27,7 @@ std::pair MeasureSolidHorizontalBounds(const CelSprite &cel, int frame * @param cel CEL sprite * @param frame CEL frame number */ -void CelDrawTo(const Surface &out, Point position, const CelSprite &cel, int frame); +void CelDrawTo(const Surface &out, Point position, CelSprite cel, int frame); /** * @briefBlit CEL sprite to the given buffer, does not perform bounds-checking. @@ -36,7 +36,7 @@ void CelDrawTo(const Surface &out, Point position, const CelSprite &cel, int fra * @param cel CEL sprite * @param frame CEL frame number */ -void CelDrawUnsafeTo(const Surface &out, Point position, const CelSprite &cel, int frame); +void CelDrawUnsafeTo(const Surface &out, Point position, CelSprite cel, int frame); /** * @brief Same as CelDrawTo but with the option to skip parts of the top and bottom of the sprite @@ -45,7 +45,7 @@ void CelDrawUnsafeTo(const Surface &out, Point position, const CelSprite &cel, i * @param cel CEL sprite * @param frame CEL frame number */ -void CelClippedDrawTo(const Surface &out, Point position, const CelSprite &cel, int frame); +void CelClippedDrawTo(const Surface &out, Point position, CelSprite cel, int frame); /** * @brief Blit CEL sprite, and apply lighting, to the back buffer at the given coordinates @@ -54,7 +54,7 @@ void CelClippedDrawTo(const Surface &out, Point position, const CelSprite &cel, * @param cel CEL sprite * @param frame CEL frame number */ -void CelDrawLightTo(const Surface &out, Point position, const CelSprite &cel, int frame, uint8_t *tbl); +void CelDrawLightTo(const Surface &out, Point position, CelSprite cel, int frame, uint8_t *tbl); /** * @brief Same as CelDrawLightTo but with the option to skip parts of the top and bottom of the sprite @@ -63,7 +63,7 @@ void CelDrawLightTo(const Surface &out, Point position, const CelSprite &cel, in * @param cel CEL sprite * @param frame CEL frame number */ -void CelClippedDrawLightTo(const Surface &out, Point position, const CelSprite &cel, int frame); +void CelClippedDrawLightTo(const Surface &out, Point position, CelSprite cel, int frame); /** * @brief Same as CelBlitLightSafeTo but with transparency applied @@ -72,7 +72,7 @@ void CelClippedDrawLightTo(const Surface &out, Point position, const CelSprite & * @param cel CEL sprite * @param frame CEL frame number */ -void CelClippedBlitLightTransTo(const Surface &out, Point position, const CelSprite &cel, int frame); +void CelClippedBlitLightTransTo(const Surface &out, Point position, CelSprite cel, int frame); /** * @brief Blit CEL sprite, and apply lighting, to the back buffer at the given coordinates, translated to a red hue @@ -81,7 +81,7 @@ void CelClippedBlitLightTransTo(const Surface &out, Point position, const CelSpr * @param cel CEL sprite * @param frame CEL frame number */ -void CelDrawLightRedTo(const Surface &out, Point position, const CelSprite &cel, int frame); +void CelDrawLightRedTo(const Surface &out, Point position, CelSprite cel, int frame); /** * @brief Blit item's CEL sprite recolored red if not usable, normal if usable @@ -91,7 +91,7 @@ void CelDrawLightRedTo(const Surface &out, Point position, const CelSprite &cel, * @param cel CEL sprite * @param frame CEL frame number */ -void CelDrawItem(const Item &item, const Surface &out, Point position, const CelSprite &cel, int frame); +void CelDrawItem(const Item &item, const Surface &out, Point position, CelSprite cel, int frame); /** * @brief Blit a solid colder shape one pixel larger than the given sprite shape, to the target buffer at the given coordianates @@ -102,6 +102,6 @@ void CelDrawItem(const Item &item, const Surface &out, Point position, const Cel * @param frame CEL frame number * @param skipColorIndexZero If true, color in index 0 will be treated as transparent (these are typically used for shadows in sprites) */ -void CelBlitOutlineTo(const Surface &out, uint8_t col, Point position, const CelSprite &cel, int frame, bool skipColorIndexZero = true); +void CelBlitOutlineTo(const Surface &out, uint8_t col, Point position, CelSprite cel, int frame, bool skipColorIndexZero = true); } // namespace devilution diff --git a/Source/engine/render/cl2_render.cpp b/Source/engine/render/cl2_render.cpp index 7c3fd4428..9bc49f5d1 100644 --- a/Source/engine/render/cl2_render.cpp +++ b/Source/engine/render/cl2_render.cpp @@ -763,7 +763,7 @@ void Cl2ApplyTrans(byte *p, const std::array &ttbl, int nCel) } } -void Cl2Draw(const Surface &out, int sx, int sy, const CelSprite &cel, int frame) +void Cl2Draw(const Surface &out, int sx, int sy, CelSprite cel, int frame) { assert(frame > 0); @@ -773,7 +773,7 @@ void Cl2Draw(const Surface &out, int sx, int sy, const CelSprite &cel, int frame Cl2BlitSafe(out, sx, sy, pRLEBytes, nDataSize, cel.Width(frame)); } -void Cl2DrawOutline(const Surface &out, uint8_t col, int sx, int sy, const CelSprite &cel, int frame) +void Cl2DrawOutline(const Surface &out, uint8_t col, int sx, int sy, CelSprite cel, int frame) { assert(frame > 0); @@ -783,7 +783,7 @@ void Cl2DrawOutline(const Surface &out, uint8_t col, int sx, int sy, const CelSp RenderCl2Outline(out, { sx, sy }, pRLEBytes, nDataSize, cel.Width(frame), col); } -void Cl2DrawTRN(const Surface &out, int sx, int sy, const CelSprite &cel, int frame, uint8_t *trn) +void Cl2DrawTRN(const Surface &out, int sx, int sy, CelSprite cel, int frame, uint8_t *trn) { assert(frame > 0); @@ -792,7 +792,7 @@ void Cl2DrawTRN(const Surface &out, int sx, int sy, const CelSprite &cel, int fr Cl2BlitLightSafe(out, sx, sy, pRLEBytes, nDataSize, cel.Width(frame), trn); } -void Cl2DrawLight(const Surface &out, int sx, int sy, const CelSprite &cel, int frame) +void Cl2DrawLight(const Surface &out, int sx, int sy, CelSprite cel, int frame) { assert(frame > 0); diff --git a/Source/engine/render/cl2_render.hpp b/Source/engine/render/cl2_render.hpp index 418133ad2..48b382ac4 100644 --- a/Source/engine/render/cl2_render.hpp +++ b/Source/engine/render/cl2_render.hpp @@ -30,7 +30,7 @@ void Cl2ApplyTrans(byte *p, const std::array &ttbl, int nCel); * @param pCelBuff CL2 buffer * @param nCel CL2 frame number */ -void Cl2Draw(const Surface &out, int sx, int sy, const CelSprite &cel, int frame); +void Cl2Draw(const Surface &out, int sx, int sy, CelSprite cel, int frame); /** * @brief Blit a solid colder shape one pixel larger than the given sprite shape, to the given buffer at the given coordianates @@ -41,7 +41,7 @@ void Cl2Draw(const Surface &out, int sx, int sy, const CelSprite &cel, int frame * @param pCelBuff CL2 buffer * @param nCel CL2 frame number */ -void Cl2DrawOutline(const Surface &out, uint8_t col, int sx, int sy, const CelSprite &cel, int frame); +void Cl2DrawOutline(const Surface &out, uint8_t col, int sx, int sy, CelSprite cel, int frame); /** * @brief Blit CL2 sprite, and apply given TRN to the given buffer at the given coordinates @@ -52,7 +52,7 @@ void Cl2DrawOutline(const Surface &out, uint8_t col, int sx, int sy, const CelSp * @param nCel CL2 frame number * @param TRN to use */ -void Cl2DrawTRN(const Surface &out, int sx, int sy, const CelSprite &cel, int frame, uint8_t *trn); +void Cl2DrawTRN(const Surface &out, int sx, int sy, CelSprite cel, int frame, uint8_t *trn); /** * @brief Blit CL2 sprite, and apply lighting, to the given buffer at the given coordinates @@ -62,6 +62,6 @@ void Cl2DrawTRN(const Surface &out, int sx, int sy, const CelSprite &cel, int fr * @param pCelBuff CL2 buffer * @param nCel CL2 frame number */ -void Cl2DrawLight(const Surface &out, int sx, int sy, const CelSprite &cel, int frame); +void Cl2DrawLight(const Surface &out, int sx, int sy, CelSprite cel, int frame); } // namespace devilution diff --git a/Source/engine/render/text_render.cpp b/Source/engine/render/text_render.cpp index bd02f39db..7fca6d12a 100644 --- a/Source/engine/render/text_render.cpp +++ b/Source/engine/render/text_render.cpp @@ -25,7 +25,7 @@ namespace devilution { -std::optional pSPentSpn2Cels; +std::optional pSPentSpn2Cels; namespace { diff --git a/Source/engine/render/text_render.hpp b/Source/engine/render/text_render.hpp index 179fba077..05cb13f6c 100644 --- a/Source/engine/render/text_render.hpp +++ b/Source/engine/render/text_render.hpp @@ -123,7 +123,7 @@ private: * * Also used in the stores and the quest log. */ -extern std::optional pSPentSpn2Cels; +extern std::optional pSPentSpn2Cels; void LoadSmallSelectionSpinner(); diff --git a/Source/gendung.cpp b/Source/gendung.cpp index b2f5c01e5..ab4356830 100644 --- a/Source/gendung.cpp +++ b/Source/gendung.cpp @@ -24,7 +24,7 @@ int setpc_w; int setpc_h; std::unique_ptr pSetPiece; bool setloadflag; -std::optional pSpecialCels; +std::optional pSpecialCels; std::unique_ptr pMegaTiles; std::unique_ptr pLevelPieces; std::unique_ptr pDungeonCels; diff --git a/Source/gendung.h b/Source/gendung.h index 836f5ca2a..48ecceb6b 100644 --- a/Source/gendung.h +++ b/Source/gendung.h @@ -150,7 +150,7 @@ extern int setpc_h; extern std::unique_ptr pSetPiece; /** Specifies whether a single player quest DUN has been loaded. */ extern bool setloadflag; -extern std::optional pSpecialCels; +extern std::optional pSpecialCels; /** Specifies the tile definitions of the active dungeon type; (e.g. levels/l1data/l1.til). */ extern std::unique_ptr pMegaTiles; extern std::unique_ptr pLevelPieces; diff --git a/Source/gmenu.cpp b/Source/gmenu.cpp index 125fa75f3..d337e4a89 100644 --- a/Source/gmenu.cpp +++ b/Source/gmenu.cpp @@ -24,10 +24,10 @@ namespace devilution { namespace { -std::optional optbar_cel; -std::optional PentSpin_cel; -std::optional option_cel; -std::optional sgpLogo; +std::optional optbar_cel; +std::optional PentSpin_cel; +std::optional option_cel; +std::optional sgpLogo; bool mouseNavigation; TMenuItem *sgpCurrItem; int LogoAnim_tick; diff --git a/Source/interfac.cpp b/Source/interfac.cpp index 3eb9eb323..1324d3928 100644 --- a/Source/interfac.cpp +++ b/Source/interfac.cpp @@ -26,7 +26,7 @@ namespace devilution { namespace { -std::optional sgpBackCel; +std::optional sgpBackCel; uint32_t sgdwProgress; int progress_id; diff --git a/Source/inv.cpp b/Source/inv.cpp index 8ccf6d991..aa41581b1 100644 --- a/Source/inv.cpp +++ b/Source/inv.cpp @@ -134,7 +134,7 @@ const Point InvRect[] = { namespace { -std::optional pInvCels; +std::optional pInvCels; void InvDrawSlotBack(const Surface &out, Point targetPosition, Size size) { diff --git a/Source/items.cpp b/Source/items.cpp index 33c16c06b..f9be560dd 100644 --- a/Source/items.cpp +++ b/Source/items.cpp @@ -127,7 +127,7 @@ _sfx_id ItemInvSnds[] = { namespace { -std::optional itemanims[ITEMTYPES]; +std::optional itemanims[ITEMTYPES]; enum class PlayerArmorGraphic : uint8_t { // clang-format off @@ -2405,7 +2405,7 @@ void CreateMagicItem(Point position, int lvl, ItemType itemType, int imid, int i int idx = RndTypeItems(itemType, imid, lvl); while (true) { - memset(&item, 0, sizeof(item)); + item = {}; SetupAllItems(item, idx, AdvanceRndSeed(), 2 * lvl, 1, true, false, delta); if (item._iCurs == icurs) break; @@ -2875,13 +2875,13 @@ void CalcPlrItemVals(Player &player, bool loadgfx) player._pgfxnum = gfxNum; ResetPlayerGFX(player); SetPlrAnims(player); - player.pPreviewCelSprite = nullptr; + player.previewCelSprite = std::nullopt; if (player._pmode == PM_STAND) { LoadPlrGFX(player, player_graphic::Stand); - player.AnimInfo.ChangeAnimationData(&*player.AnimationData[static_cast(player_graphic::Stand)].GetCelSpritesForDirection(player._pdir), player._pNFrames, 4); + player.AnimInfo.ChangeAnimationData(player.AnimationData[static_cast(player_graphic::Stand)].GetCelSpritesForDirection(player._pdir), player._pNFrames, 4); } else { LoadPlrGFX(player, player_graphic::Walk); - player.AnimInfo.ChangeAnimationData(&*player.AnimationData[static_cast(player_graphic::Walk)].GetCelSpritesForDirection(player._pdir), player._pWFrames, 1); + player.AnimInfo.ChangeAnimationData(player.AnimationData[static_cast(player_graphic::Walk)].GetCelSpritesForDirection(player._pdir), player._pWFrames, 1); } } else { player._pgfxnum = gfxNum; @@ -2919,7 +2919,7 @@ void SetPlrHandItem(Item &item, int itemData) auto &pAllItem = AllItemsList[itemData]; // zero-initialize struct - memset(&item, 0, sizeof(item)); + item = {}; item._itype = pAllItem.itype; item._iCurs = pAllItem.iCurs; @@ -3643,7 +3643,7 @@ void FreeItemGFX() void GetItemFrm(Item &item) { - item.AnimInfo.pCelSprite = &*itemanims[ItemCAnimTbl[item._iCurs]]; + item.AnimInfo.celSprite = itemanims[ItemCAnimTbl[item._iCurs]]->Unowned(); } void GetItemStr(Item &item) @@ -4582,7 +4582,7 @@ void CreateSpellBook(Point position, spell_id ispell, bool sendmsg, bool delta) auto &item = Items[ii]; while (true) { - memset(&item, 0, sizeof(*Items)); + item = {}; SetupAllItems(item, idx, AdvanceRndSeed(), 2 * lvl, 1, true, false, delta); if (item._iMiscId == IMISC_BOOK && item._iSpell == ispell) break; @@ -4705,7 +4705,7 @@ std::string DebugSpawnItem(std::string itemName) continue; Point bkp = item.position; - memset(&item, 0, sizeof(Item)); + item = {}; item.position = bkp; SetupAllItems(item, idx, AdvanceRndSeed(), fake_m.mLevel, 1, false, false, false); @@ -4771,7 +4771,7 @@ std::string DebugSpawnUniqueItem(std::string itemName) return fmt::format("Item not found in {:d} tries!", max_iter); Point bkp = item.position; - memset(&item, 0, sizeof(Item)); + item = {}; item.position = bkp; std::uniform_int_distribution dist(0, INT_MAX); SetRndSeed(dist(BetterRng)); @@ -4802,11 +4802,11 @@ void Item::SetNewAnimation(bool showAnimation) { int it = ItemCAnimTbl[_iCurs]; int numberOfFrames = ItemAnimLs[it]; - auto *pCelSprite = itemanims[it] ? &*itemanims[it] : nullptr; + auto celSprite = itemanims[it] ? std::optional { itemanims[it]->Unowned() } : std::nullopt; if (_iCurs != ICURS_MAGIC_ROCK) - AnimInfo.SetNewAnimation(pCelSprite, numberOfFrames, 1, AnimationDistributionFlags::ProcessAnimationPending, 0, numberOfFrames); + AnimInfo.SetNewAnimation(celSprite, numberOfFrames, 1, AnimationDistributionFlags::ProcessAnimationPending, 0, numberOfFrames); else - AnimInfo.SetNewAnimation(pCelSprite, numberOfFrames, 1); + AnimInfo.SetNewAnimation(celSprite, numberOfFrames, 1); _iPostDraw = false; _iRequest = false; if (showAnimation) { diff --git a/Source/items.h b/Source/items.h index 76525a0f9..aa41927e4 100644 --- a/Source/items.h +++ b/Source/items.h @@ -173,74 +173,74 @@ constexpr int ItemAnimWidth = 96; struct Item { /** Randomly generated identifier */ - int32_t _iSeed; - uint16_t _iCreateInfo; - enum ItemType _itype; - Point position; - bool _iAnimFlag; + int32_t _iSeed = 0; + uint16_t _iCreateInfo = 0; + enum ItemType _itype = ItemType::None; + Point position = { 0, 0 }; + bool _iAnimFlag = false; /* * @brief Contains Information for current Animation */ AnimationInfo AnimInfo; - bool _iDelFlag; // set when item is flagged for deletion, deprecated in 1.02 - uint8_t _iSelFlag; - bool _iPostDraw; - bool _iIdentified; - item_quality _iMagical; - char _iName[64]; - char _iIName[64]; - enum item_equip_type _iLoc; - enum item_class _iClass; - uint8_t _iCurs; - int _ivalue; - int _iIvalue; - uint8_t _iMinDam; - uint8_t _iMaxDam; - int16_t _iAC; - uint32_t _iFlags; // item_special_effect - enum item_misc_id _iMiscId; - enum spell_id _iSpell; - int _iCharges; - int _iMaxCharges; - int _iDurability; - int _iMaxDur; - int16_t _iPLDam; - int16_t _iPLToHit; - int16_t _iPLAC; - int16_t _iPLStr; - int16_t _iPLMag; - int16_t _iPLDex; - int16_t _iPLVit; - int16_t _iPLFR; - int16_t _iPLLR; - int16_t _iPLMR; - int16_t _iPLMana; - int16_t _iPLHP; - int16_t _iPLDamMod; - int16_t _iPLGetHit; - int16_t _iPLLight; - int8_t _iSplLvlAdd; - bool _iRequest; + bool _iDelFlag = false; // set when item is flagged for deletion, deprecated in 1.02 + uint8_t _iSelFlag = 0; + bool _iPostDraw = false; + bool _iIdentified = false; + item_quality _iMagical = ITEM_QUALITY_NORMAL; + char _iName[64] = {}; + char _iIName[64] = {}; + enum item_equip_type _iLoc = ILOC_NONE; + enum item_class _iClass = ICLASS_NONE; + uint8_t _iCurs = 0; + int _ivalue = 0; + int _iIvalue = 0; + uint8_t _iMinDam = 0; + uint8_t _iMaxDam = 0; + int16_t _iAC = 0; + uint32_t _iFlags = 0; // item_special_effect + enum item_misc_id _iMiscId = IMISC_NONE; + enum spell_id _iSpell = SPL_NULL; + int _iCharges = 0; + int _iMaxCharges = 0; + int _iDurability = 0; + int _iMaxDur = 0; + int16_t _iPLDam = 0; + int16_t _iPLToHit = 0; + int16_t _iPLAC = 0; + int16_t _iPLStr = 0; + int16_t _iPLMag = 0; + int16_t _iPLDex = 0; + int16_t _iPLVit = 0; + int16_t _iPLFR = 0; + int16_t _iPLLR = 0; + int16_t _iPLMR = 0; + int16_t _iPLMana = 0; + int16_t _iPLHP = 0; + int16_t _iPLDamMod = 0; + int16_t _iPLGetHit = 0; + int16_t _iPLLight = 0; + int8_t _iSplLvlAdd = 0; + bool _iRequest = false; /** Unique item ID, used as an index into UniqueItemList */ - int _iUid; - int16_t _iFMinDam; - int16_t _iFMaxDam; - int16_t _iLMinDam; - int16_t _iLMaxDam; - int16_t _iPLEnAc; - enum item_effect_type _iPrePower; - enum item_effect_type _iSufPower; - int _iVAdd1; - int _iVMult1; - int _iVAdd2; - int _iVMult2; - int8_t _iMinStr; - uint8_t _iMinMag; - int8_t _iMinDex; - bool _iStatFlag; - _item_indexes IDidx; - uint32_t dwBuff; - uint32_t _iDamAcFlags; + int _iUid = 0; + int16_t _iFMinDam = 0; + int16_t _iFMaxDam = 0; + int16_t _iLMinDam = 0; + int16_t _iLMaxDam = 0; + int16_t _iPLEnAc = 0; + enum item_effect_type _iPrePower = IPL_INVALID; + enum item_effect_type _iSufPower = IPL_INVALID; + int _iVAdd1 = 0; + int _iVMult1 = 0; + int _iVAdd2 = 0; + int _iVMult2 = 0; + int8_t _iMinStr = 0; + uint8_t _iMinMag = 0; + int8_t _iMinDex = 0; + bool _iStatFlag = false; + _item_indexes IDidx = IDI_NONE; + uint32_t dwBuff = 0; + uint32_t _iDamAcFlags = 0; /** * @brief Checks whether this item is empty or not. diff --git a/Source/loadsave.cpp b/Source/loadsave.cpp index cb4383149..2a1f5147d 100644 --- a/Source/loadsave.cpp +++ b/Source/loadsave.cpp @@ -1055,7 +1055,7 @@ void SavePlayer(SaveHelper &file, const Player &player) file.WriteLE(player.AnimInfo.NumberOfFrames); file.WriteLE(player.AnimInfo.CurrentFrame); // write _pAnimWidth for vanilla compatibility - int animWidth = player.AnimInfo.pCelSprite == nullptr ? 96 : player.AnimInfo.pCelSprite->Width(); + int animWidth = player.AnimInfo.celSprite ? player.AnimInfo.celSprite->Width() : 96; file.WriteLE(animWidth); // write _pAnimWidth2 for vanilla compatibility file.WriteLE(CalculateWidth2(animWidth)); diff --git a/Source/minitext.cpp b/Source/minitext.cpp index ecb4e3f20..ab1485dae 100644 --- a/Source/minitext.cpp +++ b/Source/minitext.cpp @@ -31,7 +31,7 @@ int qtextSpd; /** Start time of scrolling */ Uint32 ScrollStart; /** Graphics for the window border */ -std::optional pTextBoxCels; +std::optional pTextBoxCels; /** Pixels for a line of text and the empty space under it. */ const int LineHeight = 38; diff --git a/Source/missiles.cpp b/Source/missiles.cpp index 7a48eb0e6..654cc5126 100644 --- a/Source/missiles.cpp +++ b/Source/missiles.cpp @@ -2160,7 +2160,7 @@ void InitMissileAnimationFromMonster(Missile &mis, Direction midir, const Monste const AnimStruct &anim = mon.MType->GetAnimData(graphic); mis._mimfnum = static_cast(midir); mis._miAnimFlags = MissileDataFlags::None; - const auto &celSprite = *anim.CelSpritesForDirections[mis._mimfnum]; + CelSprite celSprite = *anim.GetCelSpritesForDirection(midir); mis._miAnimData = celSprite.Data(); mis._miAnimDelay = anim.Rate; mis._miAnimLen = anim.Frames; @@ -4184,7 +4184,7 @@ void missiles_process_charge() } else { graphic = MonsterGraphic::Walk; } - missile._miAnimData = mon->GetAnimData(graphic).CelSpritesForDirections[missile._mimfnum]->Data(); + missile._miAnimData = mon->GetAnimData(graphic).CelSpritesForDirections[missile._mimfnum]; } } diff --git a/Source/monster.cpp b/Source/monster.cpp index f94f572b3..f01c10cfc 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -136,6 +136,11 @@ size_t GetNumAnims(const MonsterData &monsterData) return monsterData.has_special ? 6 : 5; } +bool IsDirectionalAnim(const CMonster &monster, size_t animIndex) +{ + return monster.mtype != MT_GOLEM || animIndex < 4; +} + void InitMonsterTRN(CMonster &monst) { std::array colorTranslations; @@ -149,11 +154,15 @@ void InitMonsterTRN(CMonster &monst) continue; } - for (int j = 0; j < 8; j++) { - Cl2ApplyTrans( - CelGetFrame(monst.Anims[i].cl2Data, j), - colorTranslations, - monst.Anims[i].Frames); + AnimStruct &anim = monst.Anims[i]; + if (IsDirectionalAnim(monst, i)) { + for (int j = 0; j < 8; j++) { + Cl2ApplyTrans(anim.CelSpritesForDirections[j], colorTranslations, anim.Frames); + } + } else { + for (int j = 0; j < 8; j++) { + Cl2ApplyTrans(CelGetFrame(anim.CelSpritesForDirections[0], j), colorTranslations, anim.Frames); + } } } } @@ -680,8 +689,7 @@ void DeleteMonster(int i) void NewMonsterAnim(Monster &monster, MonsterGraphic graphic, Direction md, AnimationDistributionFlags flags = AnimationDistributionFlags::None, int numSkippedFrames = 0, int distributeFramesBeforeFrame = 0) { const auto &animData = monster.MType->GetAnimData(graphic); - const auto *pCelSprite = &*animData.CelSpritesForDirections[static_cast(md)]; - monster.AnimInfo.SetNewAnimation(pCelSprite, animData.Frames, animData.Rate, flags, numSkippedFrames, distributeFramesBeforeFrame); + monster.AnimInfo.SetNewAnimation(animData.GetCelSpritesForDirection(md), animData.Frames, animData.Rate, flags, numSkippedFrames, distributeFramesBeforeFrame); monster._mFlags &= ~(MFLAG_LOCK_ANIMATION | MFLAG_ALLOW_SPECIAL); monster._mdir = md; } @@ -3726,17 +3734,18 @@ void InitMonsterGFX(int monst) continue; } - anim.cl2Data = &monster.animData[animOffsets[animIndex]]; anim.Frames = monsterData.Frames[animIndex]; anim.Rate = monsterData.Rate[animIndex]; + anim.Width = width; - if (monster.mtype != MT_GOLEM || (animletter[animIndex] != 's' && animletter[animIndex] != 'd')) { + byte *cl2Data = &monster.animData[animOffsets[animIndex]]; + if (IsDirectionalAnim(monster, animIndex)) { for (int i = 0; i < 8; i++) { - anim.CelSpritesForDirections[i].emplace(CelGetFrame(anim.cl2Data, i), width); + anim.CelSpritesForDirections[i] = CelGetFrame(cl2Data, i); } } else { for (int i = 0; i < 8; i++) { - anim.CelSpritesForDirections[i].emplace(anim.cl2Data, width); + anim.CelSpritesForDirections[i] = cl2Data; } } } diff --git a/Source/monster.h b/Source/monster.h index c8eb7654b..1edb3eeec 100644 --- a/Source/monster.h +++ b/Source/monster.h @@ -132,14 +132,16 @@ enum class LeaderRelation : uint8_t { }; struct AnimStruct { - byte *cl2Data; - std::array, 8> CelSpritesForDirections; - - inline const std::optional &GetCelSpritesForDirection(Direction direction) const + [[nodiscard]] std::optional GetCelSpritesForDirection(Direction direction) const { - return CelSpritesForDirections[static_cast(direction)]; + const byte *spriteData = CelSpritesForDirections[static_cast(direction)]; + if (spriteData == nullptr) + return std::nullopt; + return CelSprite(spriteData, static_cast(Width)); } + std::array CelSpritesForDirections; + unsigned Width; int Frames; int Rate; }; @@ -230,10 +232,9 @@ struct Monster { // note: missing field _mAFNum void ChangeAnimationData(MonsterGraphic graphic, Direction direction) { auto &animationData = this->MType->GetAnimData(graphic); - auto &celSprite = animationData.GetCelSpritesForDirection(direction); // Passing the Frames and Rate properties here is only relevant when initialising a monster, but doesn't cause any harm when switching animations. - this->AnimInfo.ChangeAnimationData(celSprite ? &*celSprite : nullptr, animationData.Frames, animationData.Rate); + this->AnimInfo.ChangeAnimationData(animationData.GetCelSpritesForDirection(direction), animationData.Frames, animationData.Rate); } /** diff --git a/Source/panels/charpanel.cpp b/Source/panels/charpanel.cpp index 5a838da53..11512268b 100644 --- a/Source/panels/charpanel.cpp +++ b/Source/panels/charpanel.cpp @@ -16,7 +16,7 @@ namespace devilution { -std::optional pChrButtons; +std::optional pChrButtons; /** Map of hero class names */ const char *const ClassStrTbl[] = { diff --git a/Source/panels/charpanel.hpp b/Source/panels/charpanel.hpp index e5e21605d..7cb1fb8e2 100644 --- a/Source/panels/charpanel.hpp +++ b/Source/panels/charpanel.hpp @@ -6,7 +6,7 @@ namespace devilution { -extern std::optional pChrButtons; +extern std::optional pChrButtons; extern const char *const ClassStrTbl[]; void DrawChr(const Surface &); diff --git a/Source/panels/info_box.cpp b/Source/panels/info_box.cpp index 6abfee2d2..192bd49b7 100644 --- a/Source/panels/info_box.cpp +++ b/Source/panels/info_box.cpp @@ -4,8 +4,8 @@ namespace devilution { -std::optional pSTextBoxCels; -std::optional pSTextSlidCels; +std::optional pSTextBoxCels; +std::optional pSTextSlidCels; void InitInfoBoxGfx() { diff --git a/Source/panels/info_box.hpp b/Source/panels/info_box.hpp index 8b541601e..b93e77ee2 100644 --- a/Source/panels/info_box.hpp +++ b/Source/panels/info_box.hpp @@ -10,14 +10,14 @@ namespace devilution { * * Used in stores, the quest log, the help window, and the unique item info window. */ -extern std::optional pSTextBoxCels; +extern std::optional pSTextBoxCels; /** * @brief Info box scrollbar graphics. * * Used in stores and `DrawDiabloMsg`. */ -extern std::optional pSTextSlidCels; +extern std::optional pSTextSlidCels; void InitInfoBoxGfx(); void FreeInfoBoxGfx(); diff --git a/Source/panels/spell_book.cpp b/Source/panels/spell_book.cpp index 930f43d35..6f5a9e0f0 100644 --- a/Source/panels/spell_book.cpp +++ b/Source/panels/spell_book.cpp @@ -21,12 +21,12 @@ namespace devilution { -std::optional pSBkIconCels; +std::optional pSBkIconCels; namespace { -std::optional pSBkBtnCel; -std::optional pSpellBkCel; +std::optional pSBkBtnCel; +std::optional pSpellBkCel; /** Maps from spellbook page number and position to spell_id. */ spell_id SpellPages[6][7] = { diff --git a/Source/panels/spell_icons.cpp b/Source/panels/spell_icons.cpp index b5eb20ebf..ad2db2a48 100644 --- a/Source/panels/spell_icons.cpp +++ b/Source/panels/spell_icons.cpp @@ -9,7 +9,7 @@ namespace devilution { namespace { -std::optional pSpellCels; +std::optional pSpellCels; uint8_t SplTransTbl[256]; } // namespace @@ -87,7 +87,7 @@ void DrawSpellCel(const Surface &out, Point position, int nCel) DrawSpellCel(out, position, *pSpellCels, nCel); } -void DrawSpellCel(const Surface &out, Point position, const CelSprite &sprite, int nCel) +void DrawSpellCel(const Surface &out, Point position, const OwnedCelSprite &sprite, int nCel) { CelDrawLightTo(out, position, sprite, nCel, SplTransTbl); } diff --git a/Source/panels/spell_icons.hpp b/Source/panels/spell_icons.hpp index e2ecc97da..25f99ef6c 100644 --- a/Source/panels/spell_icons.hpp +++ b/Source/panels/spell_icons.hpp @@ -27,7 +27,7 @@ void DrawSpellCel(const Surface &out, Point position, int nCel); * @param sprite Icons sprite sheet. * @param nCel Index of the cel frame to draw. 0 based. */ -void DrawSpellCel(const Surface &out, Point position, const CelSprite &sprite, int nCel); +void DrawSpellCel(const Surface &out, Point position, const OwnedCelSprite &sprite, int nCel); void SetSpellTrans(spell_type t); diff --git a/Source/player.cpp b/Source/player.cpp index 97088a324..5e34ba510 100644 --- a/Source/player.cpp +++ b/Source/player.cpp @@ -2270,9 +2270,9 @@ void Player::UpdatePreviewCelSprite(_cmd_id cmdId, Point point, uint16_t wParam1 return; LoadPlrGFX(*this, *graphic); - auto &celSprites = AnimationData[static_cast(*graphic)].CelSpritesForDirections[static_cast(dir)]; - if (celSprites && pPreviewCelSprite != &*celSprites) { - pPreviewCelSprite = &*celSprites; + std::optional celSprites = AnimationData[static_cast(*graphic)].GetCelSpritesForDirection(dir); + if (celSprites && previewCelSprite != celSprites) { + previewCelSprite = celSprites; progressToNextGameTickWhenPreviewWasSet = gfProgressToNextGameTick; } } @@ -2401,7 +2401,7 @@ void InitPlayerGFX(Player &player) void ResetPlayerGFX(Player &player) { - player.AnimInfo.pCelSprite = nullptr; + player.AnimInfo.celSprite = std::nullopt; for (auto &animData : player.AnimationData) { for (auto &celSprite : animData.CelSpritesForDirections) celSprite = std::nullopt; @@ -2413,14 +2413,12 @@ void NewPlrAnim(Player &player, player_graphic graphic, Direction dir, int numbe { LoadPlrGFX(player, graphic); - auto &celSprite = player.AnimationData[static_cast(graphic)].CelSpritesForDirections[static_cast(dir)]; - - CelSprite *pCelSprite = celSprite ? &*celSprite : nullptr; + std::optional celSprite = player.AnimationData[static_cast(graphic)].GetCelSpritesForDirection(dir); float previewShownGameTickFragments = 0.F; - if (pCelSprite == player.pPreviewCelSprite && !player.IsWalking()) + if (celSprite == player.previewCelSprite && !player.IsWalking()) previewShownGameTickFragments = clamp(1.F - player.progressToNextGameTickWhenPreviewWasSet, 0.F, 1.F); - player.AnimInfo.SetNewAnimation(pCelSprite, numberOfFrames, delayLen, flags, numSkippedFrames, distributeFramesBeforeFrame, previewShownGameTickFragments); + player.AnimInfo.SetNewAnimation(celSprite, numberOfFrames, delayLen, flags, numSkippedFrames, distributeFramesBeforeFrame, previewShownGameTickFragments); } void SetPlrAnims(Player &player) @@ -3488,7 +3486,7 @@ void ProcessPlayers() CheckNewPath(pnum, tplayer); } while (tplayer); - player.pPreviewCelSprite = nullptr; + player.previewCelSprite = std::nullopt; player.AnimInfo.ProcessAnimation(); } } @@ -3711,7 +3709,7 @@ void SyncPlrAnim(int pnum) app_fatal("SyncPlrAnim"); } - player.AnimInfo.pCelSprite = &*player.AnimationData[static_cast(graphic)].CelSpritesForDirections[static_cast(player._pdir)]; + player.AnimInfo.celSprite = player.AnimationData[static_cast(graphic)].GetCelSpritesForDirection(player._pdir); // Ensure ScrollInfo is initialized correctly ScrollViewPort(player, WalkSettings[static_cast(player._pdir)].scrollDir); } diff --git a/Source/player.h b/Source/player.h index 204fb6b48..ba4d0fe5e 100644 --- a/Source/player.h +++ b/Source/player.h @@ -201,7 +201,7 @@ struct PlayerAnimationData { */ std::unique_ptr RawData; - inline const std::optional &GetCelSpritesForDirection(Direction direction) const + [[nodiscard]] std::optional GetCelSpritesForDirection(Direction direction) const { return CelSpritesForDirections[static_cast(direction)]; } @@ -231,9 +231,9 @@ struct Player { /** * @brief Contains a optional preview CelSprite that is displayed until the current command is handled by the game logic */ - CelSprite *pPreviewCelSprite; + std::optional previewCelSprite; /** - * @brief Contains the progress to next game tick when pPreviewCelSprite was set + * @brief Contains the progress to next game tick when previewCelSprite was set */ float progressToNextGameTickWhenPreviewWasSet; int _plid; @@ -689,7 +689,7 @@ struct Player { } /** - * @brief Updates pPreviewCelSprite according to new requested command + * @brief Updates previewCelSprite according to new requested command * @param cmdId What command is requested * @param point Point for the command * @param wParam1 First Parameter diff --git a/Source/qol/itemlabels.cpp b/Source/qol/itemlabels.cpp index d2b63d28d..225495605 100644 --- a/Source/qol/itemlabels.cpp +++ b/Source/qol/itemlabels.cpp @@ -77,7 +77,7 @@ void AddItemToLabelQueue(int id, int x, int y) nameWidth += MarginX * 2; int index = ItemCAnimTbl[item._iCurs]; if (!labelCenterOffsets[index]) { - std::pair itemBounds = MeasureSolidHorizontalBounds(*item.AnimInfo.pCelSprite, item.AnimInfo.CurrentFrame); + std::pair itemBounds = MeasureSolidHorizontalBounds(*item.AnimInfo.celSprite, item.AnimInfo.CurrentFrame); labelCenterOffsets[index].emplace((itemBounds.first + itemBounds.second) / 2); } diff --git a/Source/quests.cpp b/Source/quests.cpp index e1dff965a..f7dd4e641 100644 --- a/Source/quests.cpp +++ b/Source/quests.cpp @@ -29,7 +29,7 @@ namespace devilution { bool QuestLogIsOpen; -std::optional pQLogCel; +std::optional pQLogCel; /** Contains the quests of the current game. */ Quest Quests[MAXQUESTS]; Point ReturnLvlPosition; diff --git a/Source/quests.h b/Source/quests.h index d198b7d94..b70916670 100644 --- a/Source/quests.h +++ b/Source/quests.h @@ -74,7 +74,7 @@ struct QuestData { }; extern bool QuestLogIsOpen; -extern std::optional pQLogCel; +extern std::optional pQLogCel; extern DVL_API_FOR_TEST Quest Quests[MAXQUESTS]; extern Point ReturnLvlPosition; extern dungeon_type ReturnLevelType; diff --git a/Source/scrollrt.cpp b/Source/scrollrt.cpp index 327e27f55..1ad44689b 100644 --- a/Source/scrollrt.cpp +++ b/Source/scrollrt.cpp @@ -312,8 +312,8 @@ void DrawMissilePrivate(const Surface &out, const Missile &missile, Point target return; } int nCel = missile._miAnimFrame; - const int frames = LoadLE32(missile._miAnimData); - if (nCel < 1 || frames > 50 || nCel > frames) { + const uint32_t frames = LoadLE32(missile._miAnimData); + if (nCel < 1 || frames > 50 || nCel > static_cast(frames)) { Log("Draw Missile 2: frame {} of {}, missile type=={}", nCel, frames, missile._mitype); return; } @@ -352,7 +352,7 @@ void DrawMissile(const Surface &out, Point tilePosition, Point targetBufferPosit */ void DrawMonster(const Surface &out, Point tilePosition, Point targetBufferPosition, const Monster &monster) { - if (monster.AnimInfo.pCelSprite == nullptr) { + if (!monster.AnimInfo.celSprite) { Log("Draw Monster \"{}\": NULL Cel Buffer", monster.mName); return; } @@ -419,7 +419,7 @@ void DrawMonster(const Surface &out, Point tilePosition, Point targetBufferPosit }; int nCel = monster.AnimInfo.GetFrameToUseForRendering(); - const uint32_t frames = LoadLE32(monster.AnimInfo.pCelSprite->Data()); + const uint32_t frames = LoadLE32(monster.AnimInfo.celSprite->Data()); if (nCel < 1 || frames > 50 || nCel > static_cast(frames)) { Log( "Draw Monster \"{}\" {}: facing {}, frame {} of {}", @@ -431,7 +431,7 @@ void DrawMonster(const Surface &out, Point tilePosition, Point targetBufferPosit return; } - const auto &cel = *monster.AnimInfo.pCelSprite; + const auto &cel = *monster.AnimInfo.celSprite; if (!IsTileLit(tilePosition)) { Cl2DrawTRN(out, targetBufferPosition.x, targetBufferPosition.y, cel, nCel, GetInfravisionTRN()); @@ -455,7 +455,7 @@ void DrawMonster(const Surface &out, Point tilePosition, Point targetBufferPosit */ void DrawPlayerIconHelper(const Surface &out, int pnum, missile_graphic_id missileGraphicId, Point position, bool lighting) { - position.x += CalculateWidth2(Players[pnum].AnimInfo.pCelSprite->Width()) - MissileSpriteData[missileGraphicId].animWidth2; + position.x += CalculateWidth2(Players[pnum].AnimInfo.celSprite->Width()) - MissileSpriteData[missileGraphicId].animWidth2; int width = MissileSpriteData[missileGraphicId].animWidth; const byte *pCelBuff = MissileSpriteData[missileGraphicId].GetFirstFrame(); @@ -509,22 +509,22 @@ void DrawPlayer(const Surface &out, int pnum, Point tilePosition, Point targetBu auto &player = Players[pnum]; - const auto *pCelSprite = player.AnimInfo.pCelSprite; + std::optional sprite = player.AnimInfo.celSprite; int nCel = player.AnimInfo.GetFrameToUseForRendering(); - if (player.pPreviewCelSprite != nullptr) { - pCelSprite = player.pPreviewCelSprite; + if (player.previewCelSprite) { + sprite = player.previewCelSprite; nCel = 1; } - if (pCelSprite == nullptr) { + if (!sprite) { Log("Drawing player {} \"{}\": NULL CelSprite", pnum, player._pName); return; } - targetBufferPosition -= { CalculateWidth2(pCelSprite == nullptr ? 96 : pCelSprite->Width()), 0 }; + targetBufferPosition -= { CalculateWidth2(sprite ? sprite->Width() : 96), 0 }; - int frames = SDL_SwapLE32(*reinterpret_cast(pCelSprite->Data())); + int frames = SDL_SwapLE32(*reinterpret_cast(sprite->Data())); if (nCel < 1 || frames > 50 || nCel > frames) { const char *szMode = "unknown action"; if (player._pmode <= PM_QUIT) @@ -541,16 +541,16 @@ void DrawPlayer(const Surface &out, int pnum, Point tilePosition, Point targetBu } if (pnum == pcursplr) - Cl2DrawOutline(out, 165, targetBufferPosition.x, targetBufferPosition.y, *pCelSprite, nCel); + Cl2DrawOutline(out, 165, targetBufferPosition.x, targetBufferPosition.y, *sprite, nCel); if (pnum == MyPlayerId) { - Cl2Draw(out, targetBufferPosition.x, targetBufferPosition.y, *pCelSprite, nCel); + Cl2Draw(out, targetBufferPosition.x, targetBufferPosition.y, *sprite, nCel); DrawPlayerIcons(out, pnum, targetBufferPosition, true); return; } if (!IsTileLit(tilePosition) || (Players[MyPlayerId]._pInfraFlag && LightTableIndex > 8)) { - Cl2DrawTRN(out, targetBufferPosition.x, targetBufferPosition.y, *pCelSprite, nCel, GetInfravisionTRN()); + Cl2DrawTRN(out, targetBufferPosition.x, targetBufferPosition.y, *sprite, nCel, GetInfravisionTRN()); DrawPlayerIcons(out, pnum, targetBufferPosition, true); return; } @@ -561,7 +561,7 @@ void DrawPlayer(const Surface &out, int pnum, Point tilePosition, Point targetBu else LightTableIndex -= 5; - Cl2DrawLight(out, targetBufferPosition.x, targetBufferPosition.y, *pCelSprite, nCel); + Cl2DrawLight(out, targetBufferPosition.x, targetBufferPosition.y, *sprite, nCel); DrawPlayerIcons(out, pnum, targetBufferPosition, false); LightTableIndex = l; @@ -581,7 +581,7 @@ void DrawDeadPlayer(const Surface &out, Point tilePosition, Point targetBufferPo auto &player = Players[i]; if (player.plractive && player._pHitPoints == 0 && player.plrlevel == (BYTE)currlevel && player.position.tile == tilePosition) { dFlags[tilePosition.x][tilePosition.y] |= DungeonFlag::DeadPlayer; - const Displacement center { CalculateWidth2(player.AnimInfo.pCelSprite == nullptr ? 96 : player.AnimInfo.pCelSprite->Width()), 0 }; + const Displacement center { CalculateWidth2(player.AnimInfo.celSprite ? player.AnimInfo.celSprite->Width() : 96), 0 }; const Point playerRenderPosition { targetBufferPosition + player.position.offset - center }; DrawPlayer(out, i, tilePosition, playerRenderPosition); } @@ -713,15 +713,15 @@ void DrawItem(const Surface &out, Point tilePosition, Point targetBufferPosition if (item._iPostDraw == pre) return; - const auto *cel = item.AnimInfo.pCelSprite; - if (cel == nullptr) { + std::optional cel = item.AnimInfo.celSprite; + if (!cel) { Log("Draw Item \"{}\" 1: NULL CelSprite", item._iIName); return; } int nCel = item.AnimInfo.GetFrameToUseForRendering(); - int frames = SDL_SwapLE32(*(DWORD *)cel->Data()); - if (nCel < 1 || frames > 50 || nCel > frames) { + const uint32_t frames = LoadLE32(cel->Data()); + if (nCel < 1 || frames > 50 || nCel > static_cast(frames)) { Log("Draw \"{}\" Item 1: frame {} of {}, item type=={}", item._iIName, nCel, frames, ItemTypeToString(item._itype)); return; } @@ -750,11 +750,12 @@ void DrawMonsterHelper(const Surface &out, Point tilePosition, Point targetBuffe auto &towner = Towners[mi]; int px = targetBufferPosition.x - CalculateWidth2(towner._tAnimWidth); const Point position { px, targetBufferPosition.y }; + CelSprite sprite { towner._tAnimData, towner._tAnimWidth }; if (mi == pcursmonst) { - CelBlitOutlineTo(out, 166, position, CelSprite(towner._tAnimData, towner._tAnimWidth), towner._tAnimFrame); + CelBlitOutlineTo(out, 166, position, sprite, towner._tAnimFrame); } assert(towner._tAnimData); - CelClippedDrawTo(out, position, CelSprite(towner._tAnimData, towner._tAnimWidth), towner._tAnimFrame); + CelClippedDrawTo(out, position, sprite, towner._tAnimFrame); return; } @@ -776,7 +777,7 @@ void DrawMonsterHelper(const Surface &out, Point tilePosition, Point targetBuffe return; } - const CelSprite &cel = *monster.AnimInfo.pCelSprite; + CelSprite cel = *monster.AnimInfo.celSprite; Displacement offset = monster.position.offset; if (monster.IsWalking()) { diff --git a/test/animationinfo_test.cpp b/test/animationinfo_test.cpp index 5662e113e..8ab51a4cc 100644 --- a/test/animationinfo_test.cpp +++ b/test/animationinfo_test.cpp @@ -75,7 +75,7 @@ void RunAnimationTest(const std::vector &vecTestData) for (TestData *x : vecTestData) { auto setNewAnimationData = dynamic_cast(x); if (setNewAnimationData != nullptr) { - animInfo.SetNewAnimation(nullptr, setNewAnimationData->_NumberOfFrames, setNewAnimationData->_DelayLen, setNewAnimationData->_Params, setNewAnimationData->_NumSkippedFrames, setNewAnimationData->_DistributeFramesBeforeFrame); + animInfo.SetNewAnimation(std::nullopt, setNewAnimationData->_NumberOfFrames, setNewAnimationData->_DelayLen, setNewAnimationData->_Params, setNewAnimationData->_NumSkippedFrames, setNewAnimationData->_DistributeFramesBeforeFrame); } auto gameTickData = dynamic_cast(x); diff --git a/test/inv_test.cpp b/test/inv_test.cpp index 366523b6a..2cd8ea107 100644 --- a/test/inv_test.cpp +++ b/test/inv_test.cpp @@ -21,7 +21,7 @@ void set_up_scroll(Item &item, spell_id spell) void clear_inventory() { for (int i = 0; i < NUM_INV_GRID_ELEM; i++) { - memset(&Players[MyPlayerId].InvList[i], 0, sizeof(Item)); + Players[MyPlayerId].InvList[i] = {}; Players[MyPlayerId].InvGrid[i] = 0; } Players[MyPlayerId]._pNumInv = 0;