diff --git a/CMake/Assets.cmake b/CMake/Assets.cmake index 20cd4ff36..f792dcfc1 100644 --- a/CMake/Assets.cmake +++ b/CMake/Assets.cmake @@ -159,6 +159,7 @@ set(devilutionx_assets txtdata/items/item_suffixes.tsv txtdata/items/itemdat.tsv txtdata/items/unique_itemdat.tsv + txtdata/missiles/missile_sprites.tsv txtdata/monsters/monstdat.tsv txtdata/monsters/unique_monstdat.tsv txtdata/sound/effects.tsv diff --git a/Source/data/iterators.hpp b/Source/data/iterators.hpp index 32f608314..23d102ab8 100644 --- a/Source/data/iterators.hpp +++ b/Source/data/iterators.hpp @@ -127,12 +127,12 @@ public: return tl::make_unexpected(DataFileField::Error::InvalidValue); } - template - [[nodiscard]] tl::expected parseIntArray(T (&destination)[N]) + template + [[nodiscard]] tl::expected parseIntArray(T *destination, size_t n) { size_t i = 0; for (const std::string_view part : SplitByChar(value(), ',')) { - if (i == N) + if (i == n) return tl::make_unexpected(Error::InvalidValue); const std::from_chars_result result = std::from_chars(part.data(), part.data() + part.size(), destination[i]); @@ -140,11 +140,23 @@ public: return mapError(result.ec); ++i; } - if (i != N) + if (i != n) return tl::make_unexpected(Error::InvalidValue); return {}; } + template + [[nodiscard]] tl::expected parseIntArray(T (&destination)[N]) + { + return parseIntArray(destination, N); + } + + template + [[nodiscard]] tl::expected parseIntArray(std::array &destination) + { + return parseIntArray(destination.data(), N); + } + template [[nodiscard]] tl::expected parseEnumList(T &destination, ParseFn &&parseFn) { diff --git a/Source/data/record_reader.hpp b/Source/data/record_reader.hpp index e65079a47..723ba7c5d 100644 --- a/Source/data/record_reader.hpp +++ b/Source/data/record_reader.hpp @@ -1,5 +1,6 @@ #pragma once +#include #include #include @@ -56,6 +57,16 @@ public: } } + template + void readIntArray(std::string_view name, std::array &out) + { + advance(); + DataFileField field = *it_; + if (tl::expected result = field.parseIntArray(out); !result.has_value()) { + DataFile::reportFatalFieldError(result.error(), filename_, name, field); + } + } + template typename std::enable_if_t, void> readFixed6(std::string_view name, T &out) diff --git a/Source/diablo.cpp b/Source/diablo.cpp index 7a64a7dd6..ac97f2767 100644 --- a/Source/diablo.cpp +++ b/Source/diablo.cpp @@ -2476,6 +2476,7 @@ int DiabloMain(int argc, char **argv) LoadPlayerDataFiles(); // TODO: We can probably load this much later (when the game is starting). + LoadMissileData(); LoadMonsterData(); LoadItemData(); diff --git a/Source/misdat.cpp b/Source/misdat.cpp index 29726f86e..8fa823a9f 100644 --- a/Source/misdat.cpp +++ b/Source/misdat.cpp @@ -5,15 +5,26 @@ */ #include "misdat.h" +#include #include +#include -#include "engine/load_cl2.hpp" -#include "engine/load_clx.hpp" +#include + +#include "data/file.hpp" +#include "data/iterators.hpp" +#include "data/record_reader.hpp" #include "missiles.h" #include "mpq/mpq_common.hpp" #include "utils/file_name_generator.hpp" #include "utils/str_cat.hpp" +#ifdef UNPACKED_MPQS +#include "engine/load_clx.hpp" +#else +#include "engine/load_cl2.hpp" +#endif + namespace devilution { namespace { @@ -143,131 +154,63 @@ const MissileData MissilesData[] = { namespace { -constexpr std::array Repeat(uint8_t v) // NOLINT(readability-identifier-length) +/** Data related to each missile graphic ID. */ +std::vector MissileSpriteData; +std::vector> MissileAnimDelays; +std::vector> MissileAnimLengths; + +size_t ToIndex(std::vector> &all, const std::array &value) { - return { v, v, v, v, v, v, v, v, v, v, v, v, v, v, v, v }; + for (size_t i = 0; i < all.size(); ++i) { + if (all[i] == value) return i; + } + all.push_back(value); + return all.size() - 1; } -const std::array MissileAnimDelays[] { - {}, - Repeat(1), - Repeat(2), - { 0, 1 }, - { 1 }, -}; +tl::expected ParseMissileGraphicsFlag(std::string_view value) +{ + if (value.empty()) return MissileGraphicsFlags::None; + if (value == "MonsterOwned") return MissileGraphicsFlags::MonsterOwned; + if (value == "NotAnimated") return MissileGraphicsFlags::NotAnimated; + return tl::make_unexpected("Unknown enum value"); +} -const std::array MissileAnimLengths[] { - {}, - Repeat(1), - Repeat(4), - Repeat(6), - Repeat(7), - Repeat(8), - Repeat(9), - Repeat(10), - Repeat(12), - Repeat(13), - Repeat(14), - Repeat(15), - Repeat(16), - Repeat(17), - Repeat(19), - Repeat(20), - { 9, 4 }, - { 15, 14, 3 }, - { 13, 11 }, - { 16, 16, 16, 16, 16, 16, 16, 16, 8 } -}; +void LoadMissileSpriteData() +{ + const std::string_view filename = "txtdata\\missiles\\missile_sprites.tsv"; + DataFile dataFile = DataFile::loadOrDie(filename); + dataFile.skipHeaderOrDie(filename); -constexpr uint8_t AnimLen_0 = 0; // NOLINT(readability-identifier-naming) -constexpr uint8_t AnimLen_1 = 1; // NOLINT(readability-identifier-naming) -constexpr uint8_t AnimLen_4 = 2; // NOLINT(readability-identifier-naming) -constexpr uint8_t AnimLen_6 = 3; // NOLINT(readability-identifier-naming) -constexpr uint8_t AnimLen_7 = 4; // NOLINT(readability-identifier-naming) -constexpr uint8_t AnimLen_8 = 5; // NOLINT(readability-identifier-naming) -constexpr uint8_t AnimLen_9 = 6; // NOLINT(readability-identifier-naming) -constexpr uint8_t AnimLen_10 = 7; // NOLINT(readability-identifier-naming) -constexpr uint8_t AnimLen_12 = 8; // NOLINT(readability-identifier-naming) -constexpr uint8_t AnimLen_13 = 9; // NOLINT(readability-identifier-naming) -constexpr uint8_t AnimLen_14 = 10; // NOLINT(readability-identifier-naming) -constexpr uint8_t AnimLen_15 = 11; // NOLINT(readability-identifier-naming) -constexpr uint8_t AnimLen_16 = 12; // NOLINT(readability-identifier-naming) -constexpr uint8_t AnimLen_17 = 13; // NOLINT(readability-identifier-naming) -constexpr uint8_t AnimLen_19 = 14; // NOLINT(readability-identifier-naming) -constexpr uint8_t AnimLen_20 = 15; // NOLINT(readability-identifier-naming) -constexpr uint8_t AnimLen_9_4 = 16; // NOLINT(readability-identifier-naming) -constexpr uint8_t AnimLen_15_14_3 = 17; // NOLINT(readability-identifier-naming) -constexpr uint8_t AnimLen_13_11 = 18; // NOLINT(readability-identifier-naming) -constexpr uint8_t AnimLen_16x8_8 = 19; // NOLINT(readability-identifier-naming) + MissileAnimDelays.clear(); + MissileAnimLengths.clear(); + MissileSpriteData.clear(); + MissileSpriteData.reserve(dataFile.numRecords()); -} // namespace + for (DataFileRecord record : dataFile) { + RecordReader reader { record, filename }; + MissileFileData &item = MissileSpriteData.emplace_back(); + reader.advance(); // skip id + reader.readInt("width", item.animWidth); + reader.readInt("width2", item.animWidth2); + reader.readString("name", item.name); + reader.readInt("numFrames", item.animFAmt); + reader.read("flags", item.flags, ParseMissileGraphicsFlag); -/** Data related to each missile graphic ID. */ -MissileFileData MissileSpriteData[] = { - // clang-format off -// id sprites, animWidth, animWidth2, name, animFAmt, flags, animDelayIdx, animLenIdx -/*Arrow*/ { {}, 96, 16, "arrows", 1, MissileGraphicsFlags::NotAnimated, 0, AnimLen_16 }, -/*Fireball*/ { {}, 96, 16, "fireba", 16, MissileGraphicsFlags::None, 0, AnimLen_14 }, -/*Guardian*/ { {}, 96, 16, "guard", 3, MissileGraphicsFlags::None, 1, AnimLen_15_14_3 }, -/*Lightning*/ { {}, 96, 16, "lghning", 1, MissileGraphicsFlags::None, 0, AnimLen_8 }, -/*FireWall*/ { {}, 128, 32, "firewal", 2, MissileGraphicsFlags::None, 0, AnimLen_13_11 }, -/*MagmaBallExplosion*/ { {}, 128, 32, "magblos", 1, MissileGraphicsFlags::None, 1, AnimLen_10 }, -/*TownPortal*/ { {}, 96, 16, "portal", 2, MissileGraphicsFlags::None, 3, AnimLen_16 }, -/*FlashBottom*/ { {}, 160, 48, "bluexfr", 1, MissileGraphicsFlags::None, 0, AnimLen_19 }, -/*FlashTop*/ { {}, 160, 48, "bluexbk", 1, MissileGraphicsFlags::None, 0, AnimLen_19 }, -/*ManaShield*/ { {}, 96, 16, "manashld", 1, MissileGraphicsFlags::NotAnimated, 0, AnimLen_1 }, -/*BloodHit*/ { {}, 96, 16, {}, 4, MissileGraphicsFlags::None, 0, AnimLen_15 }, -/*BoneHit*/ { {}, 128, 32, {}, 3, MissileGraphicsFlags::None, 2, AnimLen_8 }, -/*MetalHit*/ { {}, 96, 16, {}, 3, MissileGraphicsFlags::None, 2, AnimLen_10 }, -/*FireArrow*/ { {}, 96, 16, "farrow", 16, MissileGraphicsFlags::None, 0, AnimLen_4 }, -/*DoomSerpents*/ { {}, 96, 16, "doom", 9, MissileGraphicsFlags::MonsterOwned, 1, AnimLen_15 }, -/*Golem*/ { {}, 0, 0, {}, 1, MissileGraphicsFlags::MonsterOwned, 0, AnimLen_0 }, -/*Spurt*/ { {}, 128, 32, {}, 2, MissileGraphicsFlags::None, 2, AnimLen_8 }, -/*ApocalypseBoom*/ { {}, 96, 16, "newexp", 1, MissileGraphicsFlags::None, 1, AnimLen_15 }, -/*StoneCurseShatter*/ { {}, 128, 32, "shatter1", 1, MissileGraphicsFlags::None, 1, AnimLen_12 }, -/*BigExplosion*/ { {}, 160, 48, "bigexp", 1, MissileGraphicsFlags::None, 0, AnimLen_15 }, -/*Inferno*/ { {}, 96, 16, "inferno", 1, MissileGraphicsFlags::None, 0, AnimLen_20 }, -/*ThinLightning*/ { {}, 96, 16, "thinlght", 1, MissileGraphicsFlags::MonsterOwned, 0, AnimLen_8 }, -/*BloodStar*/ { {}, 128, 32, "flare", 1, MissileGraphicsFlags::None, 0, AnimLen_16 }, -/*BloodStarExplosion*/ { {}, 128, 32, "flareexp", 1, MissileGraphicsFlags::None, 0, AnimLen_7 }, -/*MagmaBall*/ { {}, 128, 32, "magball", 8, MissileGraphicsFlags::MonsterOwned, 1, AnimLen_16 }, -/*Krull*/ { {}, 96, 16, "krull", 1, MissileGraphicsFlags::MonsterOwned, 0, AnimLen_14 }, -/*ChargedBolt*/ { {}, 64, 0, "miniltng", 1, MissileGraphicsFlags::None, 1, AnimLen_8 }, -/*HolyBolt*/ { {}, 96, 16, "holy", 16, MissileGraphicsFlags::None, 4, AnimLen_14 }, -/*HolyBoltExplosion*/ { {}, 160, 48, "holyexpl", 1, MissileGraphicsFlags::None, 0, AnimLen_8 }, -/*LightningArrow*/ { {}, 96, 16, "larrow", 16, MissileGraphicsFlags::None, 0, AnimLen_4 }, -/*FireArrowExplosion*/ { {}, 64, 0, {}, 1, MissileGraphicsFlags::None, 0, AnimLen_6 }, -/*Acid*/ { {}, 96, 16, "acidbf", 16, MissileGraphicsFlags::MonsterOwned, 0, AnimLen_8 }, -/*AcidSplat*/ { {}, 96, 16, "acidspla", 1, MissileGraphicsFlags::MonsterOwned, 0, AnimLen_8 }, -/*AcidPuddle*/ { {}, 96, 16, "acidpud", 2, MissileGraphicsFlags::MonsterOwned, 0, AnimLen_9_4 }, -/*Etherealize*/ { {}, 96, 16, {}, 1, MissileGraphicsFlags::None, 0, AnimLen_1 }, -/*Elemental*/ { {}, 96, 16, "firerun", 8, MissileGraphicsFlags::None, 1, AnimLen_12 }, -/*Resurrect*/ { {}, 96, 16, "ressur1", 1, MissileGraphicsFlags::None, 0, AnimLen_16 }, -/*BoneSpirit*/ { {}, 96, 16, "sklball", 9, MissileGraphicsFlags::None, 1, AnimLen_16x8_8 }, -/*RedPortal*/ { {}, 96, 16, "rportal", 2, MissileGraphicsFlags::None, 0, AnimLen_16 }, -/*DiabloApocalypseBoom*/ { {}, 160, 48, "fireplar", 1, MissileGraphicsFlags::MonsterOwned, 1, AnimLen_17 }, -/*BloodStarBlue*/ { {}, 96, 16, "scubmisb", 1, MissileGraphicsFlags::MonsterOwned, 0, AnimLen_16 }, -/*BloodStarBlueExplosion*/ { {}, 128, 32, "scbsexpb", 1, MissileGraphicsFlags::MonsterOwned, 0, AnimLen_6 }, -/*BloodStarYellow*/ { {}, 96, 16, "scubmisc", 1, MissileGraphicsFlags::MonsterOwned, 0, AnimLen_16 }, -/*BloodStarYellowExplosion*/ { {}, 128, 32, "scbsexpc", 1, MissileGraphicsFlags::MonsterOwned, 0, AnimLen_6 }, -/*BloodStarRed*/ { {}, 96, 16, "scubmisd", 1, MissileGraphicsFlags::MonsterOwned, 0, AnimLen_16 }, -/*BloodStarRedExplosion*/ { {}, 128, 32, "scbsexpd", 1, MissileGraphicsFlags::MonsterOwned, 0, AnimLen_6 }, -/*HorkSpawn*/ { {}, 96, 16, "spawns", 8, MissileGraphicsFlags::MonsterOwned, 0, AnimLen_9 }, -/*Reflect*/ { {}, 160, 64, "reflect", 1, MissileGraphicsFlags::NotAnimated, 0, AnimLen_1 }, -/*OrangeFlare*/ { {}, 96, 8, "ms_ora", 16, MissileGraphicsFlags::MonsterOwned, 0, AnimLen_15 }, -/*BlueFlare*/ { {}, 96, 8, "ms_bla", 16, MissileGraphicsFlags::MonsterOwned, 0, AnimLen_15 }, -/*RedFlare*/ { {}, 96, 8, "ms_reb", 16, MissileGraphicsFlags::MonsterOwned, 0, AnimLen_15 }, -/*YellowFlare*/ { {}, 96, 8, "ms_yeb", 16, MissileGraphicsFlags::MonsterOwned, 0, AnimLen_15 }, -/*Rune*/ { {}, 96, 8, "rglows1", 1, MissileGraphicsFlags::None, 0, AnimLen_10 }, -/*YellowFlareExplosion*/ { {}, 220, 78, "ex_yel2", 1, MissileGraphicsFlags::MonsterOwned, 0, AnimLen_10 }, -/*BlueFlareExplosion*/ { {}, 212, 86, "ex_blu2", 1, MissileGraphicsFlags::MonsterOwned, 0, AnimLen_10 }, -/*RedFlareExplosion*/ { {}, 292, 114, "ex_red3", 1, MissileGraphicsFlags::MonsterOwned, 0, AnimLen_7 }, -/*BlueFlare2*/ { {}, 96, 8, "ms_blb", 16, MissileGraphicsFlags::MonsterOwned, 0, AnimLen_15 }, -/*OrangeFlareExplosion*/ { {}, 96, -12, "ex_ora1", 1, MissileGraphicsFlags::MonsterOwned, 0, AnimLen_13 }, -/*BlueFlareExplosion2*/ { {}, 292, 114, "ex_blu3", 1, MissileGraphicsFlags::MonsterOwned, 0, AnimLen_7 }, -/*None*/ { {}, 0, 0, {}, 0, MissileGraphicsFlags::None, 0, 0 }, - // clang-format on -}; + std::array arr; + reader.readIntArray("frameDelay", arr); + item.animDelayIdx = static_cast(ToIndex(MissileAnimDelays, arr)); + + reader.readIntArray("frameLength", arr); + item.animLenIdx = static_cast(ToIndex(MissileAnimLengths, arr)); + } + + MissileSpriteData.shrink_to_fit(); + MissileAnimDelays.shrink_to_fit(); + MissileAnimLengths.shrink_to_fit(); +} + +} // namespace uint8_t MissileFileData::animDelay(uint8_t dir) const { @@ -303,12 +246,22 @@ void MissileFileData::LoadGFX() #endif } +MissileFileData &GetMissileSpriteData(MissileGraphicID graphicId) +{ + return MissileSpriteData[static_cast>(graphicId)]; +} + +void LoadMissileData() +{ + LoadMissileSpriteData(); +} + void InitMissileGFX(bool loadHellfireGraphics) { if (HeadlessMode) return; - for (size_t mi = 0; MissileSpriteData[mi].animFAmt != 0; mi++) { + for (size_t mi = 0; mi < MissileSpriteData.size(); ++mi) { if (!loadHellfireGraphics && mi >= static_cast(MissileGraphicID::HorkSpawn)) break; if (MissileSpriteData[mi].flags == MissileGraphicsFlags::MonsterOwned) diff --git a/Source/misdat.h b/Source/misdat.h index bce258f15..e5c451b37 100644 --- a/Source/misdat.h +++ b/Source/misdat.h @@ -7,12 +7,10 @@ #include #include -#include +#include #include -#include #include "effects.h" -#include "engine.h" #include "engine/clx_sprite.hpp" #include "spelldat.h" #include "utils/enum_traits.h" @@ -172,7 +170,7 @@ struct MissileFileData { OptionalOwnedClxSpriteListOrSheet sprites; uint16_t animWidth; int8_t animWidth2; - char name[9]; + std::string name; uint8_t animFAmt; MissileGraphicsFlags flags; uint8_t animDelayIdx; @@ -206,15 +204,12 @@ extern const MissileData MissilesData[]; inline const MissileData &GetMissileData(MissileID missileId) { - return MissilesData[static_cast::type>(missileId)]; + return MissilesData[static_cast>(missileId)]; } -extern MissileFileData MissileSpriteData[]; +MissileFileData &GetMissileSpriteData(MissileGraphicID graphicId); -inline MissileFileData &GetMissileSpriteData(MissileGraphicID graphicId) -{ - return MissileSpriteData[static_cast::type>(graphicId)]; -} +void LoadMissileData(); void InitMissileGFX(bool loadHellfireGraphics = false); void FreeMissileGFX(); diff --git a/Source/missiles.cpp b/Source/missiles.cpp index a2296609e..d9ea9c9dc 100644 --- a/Source/missiles.cpp +++ b/Source/missiles.cpp @@ -594,10 +594,19 @@ void MoveMissileAndCheckMissileCol(Missile &missile, DamageType damageType, int void SetMissAnim(Missile &missile, MissileGraphicID animtype) { - int dir = missile._mimfnum; - - if (animtype > MissileGraphicID::None) { - animtype = MissileGraphicID::None; + const int dir = missile._mimfnum; + + if (animtype >= MissileGraphicID::None) { + missile._miAnimType = MissileGraphicID::None; + missile._miAnimData = std::nullopt; + missile._miAnimWidth = 0; + missile._miAnimWidth2 = 0; + missile._miAnimFlags = MissileGraphicsFlags::None; + missile._miAnimDelay = 0; + missile._miAnimLen = 0; + missile._miAnimCnt = 0; + missile._miAnimFrame = 1; + return; } const MissileFileData &missileData = GetMissileSpriteData(animtype); diff --git a/assets/txtdata/missiles/missile_sprites.tsv b/assets/txtdata/missiles/missile_sprites.tsv new file mode 100644 index 000000000..571609e6f --- /dev/null +++ b/assets/txtdata/missiles/missile_sprites.tsv @@ -0,0 +1,60 @@ +id width width2 name numFrames flags frameDelay frameLength +Arrow 96 16 arrows 1 NotAnimated 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16 +Fireball 96 16 fireba 16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14 +Guardian 96 16 guard 3 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 15,14,3,0,0,0,0,0,0,0,0,0,0,0,0,0 +Lightning 96 16 lghning 1 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8 +FireWall 128 32 firewal 2 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 13,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +MagmaBallExplosion 128 32 magblos 1 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10 +TownPortal 96 16 portal 2 0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16 +FlashBottom 160 48 bluexfr 1 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19 +FlashTop 160 48 bluexbk 1 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19 +ManaShield 96 16 manashld 1 NotAnimated 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 +BloodHit 96 16 4 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15 +BoneHit 128 32 3 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8 +MetalHit 96 16 3 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10 +FireArrow 96 16 farrow 16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4 +DoomSerpents 96 16 doom 9 MonsterOwned 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15 +Golem 0 0 1 MonsterOwned 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +Spurt 128 32 2 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8 +ApocalypseBoom 96 16 newexp 1 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15 +StoneCurseShatter 128 32 shatter1 1 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12 +BigExplosion 160 48 bigexp 1 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15 +Inferno 96 16 inferno 1 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20 +ThinLightning 96 16 thinlght 1 MonsterOwned 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8 +BloodStar 128 32 flare 1 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16 +BloodStarExplosion 128 32 flareexp 1 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7 +MagmaBall 128 32 magball 8 MonsterOwned 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16 +Krull 96 16 krull 1 MonsterOwned 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14 +ChargedBolt 64 0 miniltng 1 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8 +HolyBolt 96 16 holy 16 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14 +HolyBoltExplosion 160 48 holyexpl 1 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8 +LightningArrow 96 16 larrow 16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4 +FireArrowExplosion 64 0 1 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6 +Acid 96 16 acidbf 16 MonsterOwned 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8 +AcidSplat 96 16 acidspla 1 MonsterOwned 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8 +AcidPuddle 96 16 acidpud 2 MonsterOwned 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 9,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +Etherealize 96 16 1 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 +Elemental 96 16 firerun 8 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12 +Resurrect 96 16 ressur1 1 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16 +BoneSpirit 96 16 sklball 9 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 16,16,16,16,16,16,16,16,8,0,0,0,0,0,0,0 +RedPortal 96 16 rportal 2 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16 +DiabloApocalypseBoom 160 48 fireplar 1 MonsterOwned 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17 +BloodStarBlue 96 16 scubmisb 1 MonsterOwned 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16 +BloodStarBlueExplosion 128 32 scbsexpb 1 MonsterOwned 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6 +BloodStarYellow 96 16 scubmisc 1 MonsterOwned 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16 +BloodStarYellowExplosion 128 32 scbsexpc 1 MonsterOwned 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6 +BloodStarRed 96 16 scubmisd 1 MonsterOwned 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16 +BloodStarRedExplosion 128 32 scbsexpd 1 MonsterOwned 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6 +HorkSpawn 96 16 spawns 8 MonsterOwned 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9 +Reflect 160 64 reflect 1 NotAnimated 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 +OrangeFlare 96 8 ms_ora 16 MonsterOwned 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15 +BlueFlare 96 8 ms_bla 16 MonsterOwned 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15 +RedFlare 96 8 ms_reb 16 MonsterOwned 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15 +YellowFlare 96 8 ms_yeb 16 MonsterOwned 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15 +Rune 96 8 rglows1 1 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10 +YellowFlareExplosion 220 78 ex_yel2 1 MonsterOwned 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10 +BlueFlareExplosion 212 86 ex_blu2 1 MonsterOwned 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10 +RedFlareExplosion 292 114 ex_red3 1 MonsterOwned 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7 +BlueFlare2 96 8 ms_blb 16 MonsterOwned 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15 +OrangeFlareExplosion 96 -12 ex_ora1 1 MonsterOwned 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13 +BlueFlareExplosion2 292 114 ex_blu3 1 MonsterOwned 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7 diff --git a/test/missiles_test.cpp b/test/missiles_test.cpp index 815ffb373..9d7a12475 100644 --- a/test/missiles_test.cpp +++ b/test/missiles_test.cpp @@ -41,6 +41,7 @@ TEST(Missiles, RotateBlockedMissileArrow) MyPlayerId = 0; MyPlayer = &Players[MyPlayerId]; *MyPlayer = {}; + LoadMissileData(); Player &player = Players[0]; // missile can be a copy or a reference, there's no nullptr check and the functions that use it don't expect the instance to be part of a global structure so it doesn't really matter for this use. diff --git a/test/timedemo_test.cpp b/test/timedemo_test.cpp index de7a28951..105f2872d 100644 --- a/test/timedemo_test.cpp +++ b/test/timedemo_test.cpp @@ -53,6 +53,7 @@ void RunTimedemo(std::string timedemoFolderName) demo::InitPlayBack(demoNumber, true); LoadPlayerDataFiles(); + LoadMissileData(); LoadMonsterData(); LoadItemData(); pfile_ui_set_hero_infos(Dummy_GetHeroInfo);