From 1cf2650ada65d4e72dfe22f889323dd17ed5847c Mon Sep 17 00:00:00 2001 From: Gleb Mazovetskiy Date: Sat, 17 Feb 2024 15:01:47 +0000 Subject: [PATCH] Extract objcurs widths into a file Read from the widths file when using the original CEL. When using CLX, use width in CLX. --- CMake/Assets.cmake | 6 + Source/cursor.cpp | 151 +++++++++-------------- Source/engine/clx_sprite.hpp | 5 + Source/inv.cpp | 3 +- Source/itemdat.cpp | 1 - Source/itemdat.h | 3 +- assets/data/inv/objcurs-widths.txt | 179 ++++++++++++++++++++++++++++ assets/data/inv/objcurs2-widths.txt | 61 ++++++++++ assets/txtdata/items/itemdat.tsv | 4 +- test/inv_test.cpp | 38 ++++-- test/pack_test.cpp | 11 ++ test/player_test.cpp | 11 ++ test/writehero_test.cpp | 11 ++ 13 files changed, 378 insertions(+), 106 deletions(-) create mode 100644 assets/data/inv/objcurs-widths.txt create mode 100644 assets/data/inv/objcurs2-widths.txt diff --git a/CMake/Assets.cmake b/CMake/Assets.cmake index da98f020e0a..6a735014052 100644 --- a/CMake/Assets.cmake +++ b/CMake/Assets.cmake @@ -173,6 +173,12 @@ set(devilutionx_assets ui_art/mainmenuw.clx ui_art/supportw.clx) +if(NOT UNPACKED_MPQS) + list(APPEND devilutionx_assets + data/inv/objcurs-widths.txt + data/inv/objcurs2-widths.txt) +endif() + if(NOT USE_SDL1 AND NOT VITA) list(APPEND devilutionx_assets ui_art/button.png diff --git a/Source/cursor.cpp b/Source/cursor.cpp index 31e39cf30dd..c2e5dd0e6e3 100644 --- a/Source/cursor.cpp +++ b/Source/cursor.cpp @@ -7,6 +7,9 @@ #include #include +#include +#include +#include #include @@ -17,7 +20,6 @@ #include "engine.h" #include "engine/backbuffer_state.hpp" #include "engine/demomode.h" -#include "engine/load_cel.hpp" #include "engine/point.hpp" #include "engine/points_in_rectangle_range.hpp" #include "engine/render/clx_render.hpp" @@ -37,84 +39,20 @@ #include "utils/surface_to_clx.hpp" #include "utils/utf8.hpp" +#ifdef UNPACKED_MPQS +#include "engine/load_clx.hpp" +#else +#include "engine/load_cel.hpp" +#include "engine/load_file.hpp" +#include "utils/parse_int.hpp" +#endif + namespace devilution { namespace { /** Cursor images CEL */ OptionalOwnedClxSpriteList pCursCels; OptionalOwnedClxSpriteList pCursCels2; -/** Maps from objcurs.cel frame number to frame width. */ -const uint16_t InvItemWidth1[] = { - // clang-format off - // Cursors - 33, 32, 32, 32, 32, 32, 32, 32, 32, 32, 23, - // Items - 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, - 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, - 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, - 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, - 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, - 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, - 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, - 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, 2 * 28, 2 * 28, 2 * 28, 2 * 28, 2 * 28, - 2 * 28, 2 * 28, 2 * 28, 2 * 28, 2 * 28, 2 * 28, 2 * 28, 2 * 28, 2 * 28, 2 * 28, - 2 * 28, 2 * 28, 2 * 28, 2 * 28, 2 * 28, 2 * 28, 2 * 28, 2 * 28, 2 * 28, 2 * 28, - 2 * 28, 2 * 28, 2 * 28, 2 * 28, 2 * 28, 2 * 28, 2 * 28, 2 * 28, 2 * 28, 2 * 28, - 2 * 28, 2 * 28, 2 * 28, 2 * 28, 2 * 28, 2 * 28, 2 * 28, 2 * 28, 2 * 28, 2 * 28, - 2 * 28, 2 * 28, 2 * 28, 2 * 28, 2 * 28, 2 * 28, 2 * 28, 2 * 28, 2 * 28, 2 * 28, - 2 * 28, 2 * 28, 2 * 28, 2 * 28, 2 * 28, 2 * 28, 2 * 28, 2 * 28, 2 * 28, 2 * 28, - 2 * 28, 2 * 28, 2 * 28, 2 * 28, 2 * 28, 2 * 28, 2 * 28, 2 * 28, 2 * 28, 2 * 28, - 2 * 28, 2 * 28, 2 * 28, 2 * 28, 2 * 28, 2 * 28, 2 * 28, 2 * 28, 2 * 28, 2 * 28, - 2 * 28, 2 * 28, 2 * 28, 2 * 28, 2 * 28, 2 * 28, 2 * 28, 2 * 28, -}; -const uint16_t InvItemWidth2[] = { - 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, - 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, - 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, - 2 * 28, 2 * 28, 1 * 28, 1 * 28, 1 * 28, 2 * 28, 2 * 28, 2 * 28, 2 * 28, 2 * 28, - 2 * 28, 2 * 28, 2 * 28, 2 * 28, 2 * 28, 2 * 28, 2 * 28, 2 * 28, 2 * 28, 2 * 28, - 2 * 28, 2 * 28, 2 * 28, 2 * 28, 2 * 28, 2 * 28, 2 * 28, 2 * 28, 2 * 28, 2 * 28, - 2 * 28 - // clang-format on -}; -constexpr uint16_t InvItems1Size = sizeof(InvItemWidth1) / sizeof(InvItemWidth1[0]); -constexpr uint16_t InvItems2Size = sizeof(InvItemWidth2) / sizeof(InvItemWidth2[0]); - -/** Maps from objcurs.cel frame number to frame height. */ -const uint16_t InvItemHeight1[InvItems1Size] = { - // clang-format off - // Cursors - 29, 32, 32, 32, 32, 32, 32, 32, 32, 32, 35, - // Items - 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, - 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, - 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, - 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, - 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, - 2 * 28, 2 * 28, 2 * 28, 2 * 28, 2 * 28, 2 * 28, 3 * 28, 3 * 28, 3 * 28, 3 * 28, - 3 * 28, 3 * 28, 3 * 28, 3 * 28, 3 * 28, 3 * 28, 3 * 28, 3 * 28, 3 * 28, 3 * 28, - 3 * 28, 3 * 28, 3 * 28, 3 * 28, 3 * 28, 2 * 28, 2 * 28, 2 * 28, 2 * 28, 2 * 28, - 2 * 28, 2 * 28, 2 * 28, 2 * 28, 2 * 28, 2 * 28, 2 * 28, 2 * 28, 2 * 28, 2 * 28, - 2 * 28, 2 * 28, 2 * 28, 2 * 28, 2 * 28, 2 * 28, 2 * 28, 2 * 28, 2 * 28, 2 * 28, - 3 * 28, 3 * 28, 3 * 28, 3 * 28, 3 * 28, 3 * 28, 3 * 28, 3 * 28, 3 * 28, 3 * 28, - 3 * 28, 3 * 28, 3 * 28, 3 * 28, 3 * 28, 3 * 28, 3 * 28, 3 * 28, 3 * 28, 3 * 28, - 3 * 28, 3 * 28, 3 * 28, 3 * 28, 3 * 28, 3 * 28, 3 * 28, 3 * 28, 3 * 28, 3 * 28, - 3 * 28, 3 * 28, 3 * 28, 3 * 28, 3 * 28, 3 * 28, 3 * 28, 3 * 28, 3 * 28, 3 * 28, - 3 * 28, 3 * 28, 3 * 28, 3 * 28, 3 * 28, 3 * 28, 3 * 28, 3 * 28, 3 * 28, 3 * 28, - 3 * 28, 3 * 28, 3 * 28, 3 * 28, 3 * 28, 3 * 28, 3 * 28, 3 * 28, 3 * 28, 3 * 28, - 3 * 28, 3 * 28, 3 * 28, 3 * 28, 3 * 28, 3 * 28, 3 * 28, 3 * 28, -}; -const uint16_t InvItemHeight2[InvItems2Size] = { - 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, - 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, - 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, 1 * 28, - 2 * 28, 2 * 28, 3 * 28, 3 * 28, 3 * 28, 3 * 28, 3 * 28, 3 * 28, 3 * 28, 3 * 28, - 3 * 28, 3 * 28, 3 * 28, 3 * 28, 3 * 28, 3 * 28, 3 * 28, 3 * 28, 3 * 28, 3 * 28, - 3 * 28, 3 * 28, 3 * 28, 3 * 28, 3 * 28, 3 * 28, 3 * 28, 3 * 28, 3 * 28, 3 * 28, - 3 * 28 - // clang-format on -}; - OptionalOwnedClxSpriteList *HalfSizeItemSprites; OptionalOwnedClxSpriteList *HalfSizeItemSpritesRed; @@ -430,6 +368,30 @@ bool TrySelectPixelBased(Point tile) return false; } +#ifndef UNPACKED_MPQS +std::vector ReadWidths(const char *path) +{ + size_t len; + const std::unique_ptr data = LoadFileInMem(path, &len); + std::string_view str { data.get(), len }; + std::vector result; + while (!str.empty()) { + const char *end; + const ParseIntResult parseResult = ParseInt(str, std::numeric_limits::min(), + std::numeric_limits::max(), &end); + if (!parseResult.has_value()) { + app_fatal(StrCat("Failed to parse ", path, ": [", str, "]")); + } + result.push_back(parseResult.value()); + str.remove_prefix(end - str.data()); + while (!str.empty() && (str[0] == '\r' || str[0] == '\n')) { + str.remove_prefix(1); + } + } + return result; +} +#endif + } // namespace /** Current highlighted monster */ @@ -455,9 +417,17 @@ int pcurs; void InitCursor() { assert(!pCursCels); - pCursCels = LoadCel("data\\inv\\objcurs", InvItemWidth1); - if (gbIsHellfire) - pCursCels2 = LoadCel("data\\inv\\objcurs2", InvItemWidth2); +#ifdef UNPACKED_MPQS + pCursCels = LoadClx("data\\inv\\objcurs.clx"); + if (gbIsHellfire) { + pCursCels2 = LoadClx("data\\inv\\objcurs2.clx"); + } +#else + pCursCels = LoadCel("data\\inv\\objcurs", ReadWidths("data\\inv\\objcurs-widths.txt").data()); + if (gbIsHellfire) { + pCursCels2 = LoadCel("data\\inv\\objcurs2", ReadWidths("data\\inv\\objcurs2-widths.txt").data()); + } +#endif ClearCursor(); } @@ -470,22 +440,20 @@ void FreeCursor() ClxSprite GetInvItemSprite(int cursId) { - if (cursId <= InvItems1Size) + assert(cursId > 0); + const size_t numSprites = pCursCels->numSprites(); + if (static_cast(cursId) <= numSprites) { return (*pCursCels)[cursId - 1]; - return (*pCursCels2)[cursId - InvItems1Size - 1]; -} - -size_t GetNumInvItems() -{ - return InvItems1Size + InvItems2Size; + } + assert(gbIsHellfire); + assert(cursId - numSprites <= pCursCels2->numSprites()); + return (*pCursCels2)[cursId - numSprites - 1]; } Size GetInvItemSize(int cursId) { - const int i = cursId - 1; - if (i >= InvItems1Size) - return { InvItemWidth2[i - InvItems1Size], InvItemHeight2[i - InvItems1Size] }; - return { InvItemWidth1[i], InvItemHeight1[i] }; + const ClxSprite sprite = GetInvItemSprite(cursId); + return { sprite.width(), sprite.height() }; } ClxSprite GetHalfSizeItemSprite(int cursId) @@ -502,9 +470,8 @@ void CreateHalfSizeItemSprites() { if (HalfSizeItemSprites != nullptr) return; - const int numInvItems = gbIsHellfire - ? InvItems1Size + InvItems2Size - (static_cast(CURSOR_FIRSTITEM) - 1) - : InvItems1Size + (static_cast(CURSOR_FIRSTITEM) - 1); + const int numInvItems = pCursCels->numSprites() - (static_cast(CURSOR_FIRSTITEM) - 1) + + (gbIsHellfire ? pCursCels2->numSprites() : 0); HalfSizeItemSprites = new OptionalOwnedClxSpriteList[numInvItems]; HalfSizeItemSpritesRed = new OptionalOwnedClxSpriteList[numInvItems]; const uint8_t *redTrn = GetInfravisionTRN(); @@ -538,11 +505,11 @@ void CreateHalfSizeItemSprites() }; size_t outputIndex = 0; - for (size_t i = static_cast(CURSOR_FIRSTITEM) - 1; i < InvItems1Size; ++i, ++outputIndex) { + for (size_t i = static_cast(CURSOR_FIRSTITEM) - 1, n = pCursCels->numSprites(); i < n; ++i, ++outputIndex) { createHalfSize((*pCursCels)[i], outputIndex); } if (gbIsHellfire) { - for (size_t i = 0; i < InvItems2Size; ++i, ++outputIndex) { + for (size_t i = 0, n = pCursCels2->numSprites(); i < n; ++i, ++outputIndex) { createHalfSize((*pCursCels2)[i], outputIndex); } } diff --git a/Source/engine/clx_sprite.hpp b/Source/engine/clx_sprite.hpp index b451c27c502..b41e8174c68 100644 --- a/Source/engine/clx_sprite.hpp +++ b/Source/engine/clx_sprite.hpp @@ -362,6 +362,11 @@ class OwnedClxSpriteList { return ClxSpriteList { *this }[spriteIndex]; } + [[nodiscard]] uint32_t numSprites() const + { + return ClxSpriteList { *this }.numSprites(); + } + private: // For OptionalOwnedClxSpriteList. OwnedClxSpriteList() = default; diff --git a/Source/inv.cpp b/Source/inv.cpp index 5310670eae4..7d6d61eefc3 100644 --- a/Source/inv.cpp +++ b/Source/inv.cpp @@ -2154,8 +2154,7 @@ int CalculateGold(Player &player) Size GetInventorySize(const Item &item) { - int itemSizeIndex = item._iCurs + CURSOR_FIRSTITEM; - auto size = GetInvItemSize(itemSizeIndex); + auto size = GetInvItemSize(item._iCurs + CURSOR_FIRSTITEM); return { size.width / InventorySlotSizeInPixels.width, size.height / InventorySlotSizeInPixels.height }; } diff --git a/Source/itemdat.cpp b/Source/itemdat.cpp index 11767914fd1..e306d54a21f 100644 --- a/Source/itemdat.cpp +++ b/Source/itemdat.cpp @@ -175,7 +175,6 @@ tl::expected ParseItemCursorGraphic(std::strin if (value == "SHORT_WAR_BOW") return ICURS_SHORT_WAR_BOW; if (value == "COMPOSITE_STAFF") return ICURS_COMPOSITE_STAFF; if (value == "SHORT_BATTLE_BOW") return ICURS_SHORT_BATTLE_BOW; - if (value == "GOLD") return ICURS_GOLD; if (value == "AURIC_AMULET") return ICURS_AURIC_AMULET; if (value == "RUNE_BOMB") return ICURS_RUNE_BOMB; if (value == "THEODORE") return ICURS_THEODORE; diff --git a/Source/itemdat.h b/Source/itemdat.h index adeb35221b0..8df87122acc 100644 --- a/Source/itemdat.h +++ b/Source/itemdat.h @@ -71,6 +71,7 @@ enum _item_indexes : int16_t { // TODO defines all indexes in AllItemsList IDI_BOOK3, IDI_BOOK4, IDI_BARBARIAN = 139, + IDI_SHORT_BATTLE_BOW = 148, IDI_RUNEOFSTONE = 165, IDI_SORCERER_DIABLO, IDI_ARENAPOT, @@ -217,7 +218,7 @@ enum item_cursor_graphic : uint8_t { ICURS_SHORT_WAR_BOW = 165, ICURS_COMPOSITE_STAFF = 166, ICURS_SHORT_BATTLE_BOW = 167, - ICURS_GOLD = 168, + // Hellfire items: ICURS_AURIC_AMULET = 180, ICURS_RUNE_BOMB = 187, ICURS_THEODORE = 188, diff --git a/assets/data/inv/objcurs-widths.txt b/assets/data/inv/objcurs-widths.txt new file mode 100644 index 00000000000..b52d57ee19d --- /dev/null +++ b/assets/data/inv/objcurs-widths.txt @@ -0,0 +1,179 @@ +33 +32 +32 +32 +32 +32 +32 +32 +32 +32 +23 +28 +28 +28 +28 +28 +28 +28 +28 +28 +28 +28 +28 +28 +28 +28 +28 +28 +28 +28 +28 +28 +28 +28 +28 +28 +28 +28 +28 +28 +28 +28 +28 +28 +28 +28 +28 +28 +28 +28 +28 +28 +28 +28 +28 +28 +28 +28 +28 +28 +28 +28 +28 +28 +28 +28 +28 +28 +28 +28 +28 +28 +28 +28 +28 +28 +28 +28 +28 +28 +28 +28 +28 +28 +28 +28 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 diff --git a/assets/data/inv/objcurs2-widths.txt b/assets/data/inv/objcurs2-widths.txt new file mode 100644 index 00000000000..a4b95220e0f --- /dev/null +++ b/assets/data/inv/objcurs2-widths.txt @@ -0,0 +1,61 @@ +28 +28 +28 +28 +28 +28 +28 +28 +28 +28 +28 +28 +28 +28 +28 +28 +28 +28 +28 +28 +28 +28 +28 +28 +28 +28 +28 +28 +28 +28 +56 +56 +28 +28 +28 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 +56 diff --git a/assets/txtdata/items/itemdat.tsv b/assets/txtdata/items/itemdat.tsv index 5496869379e..f5f39011a1b 100644 --- a/assets/txtdata/items/itemdat.tsv +++ b/assets/txtdata/items/itemdat.tsv @@ -1,5 +1,5 @@ id dropRate class equipType cursorGraphic itemType uniqueBaseItem name shortName minMonsterLevel durability minDamage maxDamage minArmor maxArmor minStrength minMagic minDexterity specialEffects miscId spell usable value -IDI_GOLD Regular Gold Unequippable GOLD Gold NONE Gold 1 0 0 0 0 0 0 0 0 NONE Null true 0 +IDI_GOLD Regular Gold Unequippable GOLD_SMALL Gold NONE Gold 1 0 0 0 0 0 0 0 0 NONE Null true 0 IDI_WARRIOR Never Weapon One-handed SHORT_SWORD Sword NONE Short Sword 2 20 2 6 0 0 18 0 0 NONE Null false 50 IDI_WARRSHLD Never Armor One-handed BUCKLER Shield NONE Buckler 2 10 0 0 3 3 0 0 0 NONE Null false 50 IDI_WARRCLUB Never Weapon One-handed CLUB Mace SPIKCLUB Club 1 20 1 6 0 0 0 0 0 NONE Null false 20 @@ -146,7 +146,7 @@ IDI_GREYSUIT Never Quest Unequippable GREY_SUIT Misc NONE Grey Suit 0 0 0 0 0 0 Double Weapon Two-handed HUNTERS_BOW Bow HUNTBOW Hunter's Bow Bow 3 40 2 5 0 0 20 0 35 NONE Null false 350 Double Weapon Two-handed HUNTERS_BOW Bow LONGBOW Long Bow Bow 5 35 1 6 0 0 25 0 30 NONE Null false 250 Double Weapon Two-handed COMPOSITE_BOW Bow COMPBOW Composite Bow Bow 7 45 3 6 0 0 25 0 40 NONE Null false 600 - Double Weapon Two-handed SHORT_BATTLE_BOW Bow NONE Short Battle Bow Bow 9 45 3 7 0 0 30 0 50 NONE Null false 750 +IDI_SHORT_BATTLE_BOW Double Weapon Two-handed SHORT_BATTLE_BOW Bow NONE Short Battle Bow Bow 9 45 3 7 0 0 30 0 50 NONE Null false 750 Double Weapon Two-handed LONG_BATTLE_BOW Bow BATTLEBOW Long Battle Bow Bow 11 50 1 10 0 0 30 0 60 NONE Null false 1000 Double Weapon Two-handed SHORT_WAR_BOW Bow NONE Short War Bow Bow 15 55 4 8 0 0 35 0 70 NONE Null false 1500 Double Weapon Two-handed LONG_WAR_BOW Bow WARBOW Long War Bow Bow 19 60 1 14 0 0 45 0 80 NONE Null false 2000 diff --git a/test/inv_test.cpp b/test/inv_test.cpp index 29a9ba28b85..29d25e8f289 100644 --- a/test/inv_test.cpp +++ b/test/inv_test.cpp @@ -18,6 +18,14 @@ class InvTest : public ::testing::Test { static void SetUpTestSuite() { + LoadCoreArchives(); + LoadGameArchives(); + + // The tests need spawn.mpq or diabdat.mpq + // Please provide them so that the tests can run successfully + ASSERT_TRUE(HaveSpawn() || HaveDiabdat()); + + InitCursor(); LoadSpellData(); LoadItemData(); } @@ -287,26 +295,40 @@ TEST_F(InvTest, RemoveCurrentSpellScrollFirstMatchFromBelt) EXPECT_TRUE(MyPlayer->SpdList[3].isEmpty()); } -TEST_F(InvTest, ItemSize) +TEST_F(InvTest, ItemSizeRuneOfStone) { - Item testItem {}; - // Inventory sizes are currently determined by examining the sprite size // rune of stone and grey suit are adjacent in the sprite list so provide an easy check for off-by-one errors + if (!gbIsHellfire) return; + Item testItem {}; InitializeItem(testItem, IDI_RUNEOFSTONE); EXPECT_EQ(GetInventorySize(testItem), Size(1, 1)); +} + +TEST_F(InvTest, ItemSizeGreySuit) +{ + if (!gbIsHellfire) return; + Item testItem {}; InitializeItem(testItem, IDI_GREYSUIT); EXPECT_EQ(GetInventorySize(testItem), Size(2, 2)); +} - // auric amulet is the first used hellfire sprite, but there's multiple unused sprites before it in the list. +TEST_F(InvTest, ItemSizeAuric) +{ + // Auric amulet is the first used hellfire sprite, but there's multiple unused sprites before it in the list. // unfortunately they're the same size so this is less valuable as a test. + if (!gbIsHellfire) return; + Item testItem {}; InitializeItem(testItem, IDI_AURIC); EXPECT_EQ(GetInventorySize(testItem), Size(1, 1)); +} - // gold is the last diablo sprite, off by ones will end up loading a 1x1 unused sprite from hellfire but maybe - // this'll segfault if we make a mistake in the future? - InitializeItem(testItem, IDI_GOLD); - EXPECT_EQ(GetInventorySize(testItem), Size(1, 1)); +TEST_F(InvTest, ItemSizeLastDiabloItem) +{ + // Short battle bow is the last diablo sprite, off by ones will end up loading a 1x1 unused sprite from hellfire,. + Item testItem {}; + InitializeItem(testItem, IDI_SHORT_BATTLE_BOW); + EXPECT_EQ(GetInventorySize(testItem), Size(2, 3)); } } // namespace diff --git a/test/pack_test.cpp b/test/pack_test.cpp index 1601fcb92a2..fd758417453 100644 --- a/test/pack_test.cpp +++ b/test/pack_test.cpp @@ -2,6 +2,7 @@ #include +#include "cursor.h" #include "monstdat.h" #include "pack.h" #include "playerdat.hpp" @@ -879,6 +880,7 @@ class NetPackTest : public ::testing::Test { Players.resize(2); MyPlayer = &Players[0]; gbIsMultiplayer = true; + gbIsSpawn = false; PlayerPack testPack { 0, 0, -1, 9, 0, 2, 61, 24, 0, 0, "MP-Warrior", 0, 120, 25, 60, 60, 37, 0, 85670061, 3921, 13568, 13568, 3904, 3904, @@ -954,6 +956,15 @@ class NetPackTest : public ::testing::Test { static void SetUpTestSuite() { + LoadCoreArchives(); + LoadGameArchives(); + + // The tests need spawn.mpq or diabdat.mpq + // Please provide them so that the tests can run successfully + ASSERT_TRUE(HaveSpawn() || HaveDiabdat()); + + gbIsHellfire = false; + InitCursor(); LoadSpellData(); LoadPlayerDataFiles(); LoadMonsterData(); diff --git a/test/player_test.cpp b/test/player_test.cpp index a423b96988f..5d4d7a43daa 100644 --- a/test/player_test.cpp +++ b/test/player_test.cpp @@ -2,6 +2,8 @@ #include +#include "cursor.h" +#include "init.h" #include "playerdat.hpp" using namespace devilution; @@ -179,6 +181,15 @@ static void AssertPlayer(Player &player) TEST(Player, CreatePlayer) { + LoadCoreArchives(); + LoadGameArchives(); + + // The tests need spawn.mpq or diabdat.mpq + // Please provide them so that the tests can run successfully + ASSERT_TRUE(HaveSpawn() || HaveDiabdat()); + + InitCursor(); + LoadPlayerDataFiles(); LoadItemData(); Players.resize(1); diff --git a/test/writehero_test.cpp b/test/writehero_test.cpp index 88e6004418d..30d38396062 100644 --- a/test/writehero_test.cpp +++ b/test/writehero_test.cpp @@ -8,6 +8,8 @@ #include #include +#include "cursor.h" +#include "init.h" #include "loadsave.h" #include "pack.h" #include "pfile.h" @@ -360,11 +362,19 @@ void AssertPlayer(Player &player) TEST(Writehero, pfile_write_hero) { + LoadCoreArchives(); + LoadGameArchives(); + + // The tests need spawn.mpq or diabdat.mpq + // Please provide them so that the tests can run successfully + ASSERT_TRUE(HaveSpawn() || HaveDiabdat()); + paths::SetPrefPath("."); std::remove("multi_0.sv"); gbVanilla = true; gbIsHellfire = false; + gbIsSpawn = false; gbIsMultiplayer = true; gbIsHellfireSaveGame = false; leveltype = DTYPE_TOWN; @@ -374,6 +384,7 @@ TEST(Writehero, pfile_write_hero) MyPlayerId = 0; MyPlayer = &Players[MyPlayerId]; + InitCursor(); LoadSpellData(); LoadPlayerDataFiles(); LoadItemData();