From 16b65120ea76678124a3b29c5cb77ab9c8b358d8 Mon Sep 17 00:00:00 2001 From: Anders Jenbo Date: Fri, 15 Jul 2022 17:21:31 +0200 Subject: [PATCH] Clean up LevelMonsterTypes related code --- Source/dead.cpp | 9 +- Source/debug.cpp | 22 ++-- Source/diablo.cpp | 1 - Source/effects.cpp | 44 -------- Source/effects.h | 2 - Source/effects_stubs.cpp | 2 - Source/monstdat.cpp | 20 ++-- Source/monster.cpp | 226 ++++++++++++++++++++------------------- Source/monster.h | 5 +- 9 files changed, 147 insertions(+), 184 deletions(-) diff --git a/Source/dead.cpp b/Source/dead.cpp index 0288cd1c6..8e1e8150e 100644 --- a/Source/dead.cpp +++ b/Source/dead.cpp @@ -32,15 +32,16 @@ void InitCorpses() int8_t nd = 0; for (size_t i = 0; i < LevelMonsterTypeCount; i++) { - if (mtypes[LevelMonsterTypes[i].type] != 0) + CMonster &monsterType = LevelMonsterTypes[i]; + if (mtypes[monsterType.type] != 0) continue; - InitDeadAnimationFromMonster(Corpses[nd], LevelMonsterTypes[i]); + InitDeadAnimationFromMonster(Corpses[nd], monsterType); Corpses[nd].translationPaletteIndex = 0; nd++; - LevelMonsterTypes[i].corpseId = nd; - mtypes[LevelMonsterTypes[i].type] = nd; + monsterType.corpseId = nd; + mtypes[monsterType.type] = nd; } nd++; // Unused blood spatter diff --git a/Source/debug.cpp b/Source/debug.cpp index a891fe006..8bc36dd0d 100644 --- a/Source/debug.cpp +++ b/Source/debug.cpp @@ -706,11 +706,12 @@ std::string DebugCmdSpawnUniqueMonster(const string_view parameter) } if (!found) { - LevelMonsterTypes[id].type = static_cast<_monster_id>(mtype); - InitMonsterGFX(id); - InitMonsterSND(id); - LevelMonsterTypes[id].placeFlags |= PLACE_SCATTER; - LevelMonsterTypes[id].corpseId = 1; + CMonster &monsterType = LevelMonsterTypes[id]; + monsterType.type = static_cast<_monster_id>(mtype); + InitMonsterGFX(monsterType); + InitMonsterSND(monsterType); + monsterType.placeFlags |= PLACE_SCATTER; + monsterType.corpseId = 1; } Player &myPlayer = *MyPlayer; @@ -791,11 +792,12 @@ std::string DebugCmdSpawnMonster(const string_view parameter) } if (!found) { - LevelMonsterTypes[id].type = static_cast<_monster_id>(mtype); - InitMonsterGFX(id); - InitMonsterSND(id); - LevelMonsterTypes[id].placeFlags |= PLACE_SCATTER; - LevelMonsterTypes[id].corpseId = 1; + CMonster &monsterType = LevelMonsterTypes[id]; + monsterType.type = static_cast<_monster_id>(mtype); + InitMonsterGFX(monsterType); + InitMonsterSND(monsterType); + monsterType.placeFlags |= PLACE_SCATTER; + monsterType.corpseId = 1; } Player &myPlayer = *MyPlayer; diff --git a/Source/diablo.cpp b/Source/diablo.cpp index 41999e9d1..1ff4f9beb 100644 --- a/Source/diablo.cpp +++ b/Source/diablo.cpp @@ -1712,7 +1712,6 @@ void FreeGameMem() FreeMonsters(); FreeMissileGFX(); FreeObjectGFX(); - FreeMonsterSnd(); FreeTownerGFX(); #ifndef USE_SDL1 DeactivateVirtualGamepad(); diff --git a/Source/effects.cpp b/Source/effects.cpp index 6f1e6219d..936cb76a4 100644 --- a/Source/effects.cpp +++ b/Source/effects.cpp @@ -30,15 +30,6 @@ constexpr bool AllowStreaming = false; /** Specifies the sound file and the playback state of the current sound effect. */ TSFX *sgpStreamSFX = nullptr; -/** - * Monster sound type prefix - * a: Attack - * h: Hit - * d: Death - * s: Special - */ -const char MonstSndChar[] = { 'a', 'h', 'd', 's' }; - /* data */ /** List of all sounds, except monsters and music */ TSFX sgSFX[] = { @@ -1211,41 +1202,6 @@ void stream_stop() } } -void InitMonsterSND(size_t monst) -{ - if (!gbSndInited) { - return; - } - - const int mtype = LevelMonsterTypes[monst].type; - const MonsterData &data = MonstersData[mtype]; - for (int i = 0; i < 4; i++) { - if (MonstSndChar[i] != 's' || data.hasSpecialSound) { - for (int j = 0; j < 2; j++) { - char path[MAX_PATH]; - const char *sndfile = data.soundSuffix != nullptr ? data.soundSuffix : data.assetsSuffix; - *BufCopy(path, "Monsters\\", sndfile, string_view(&MonstSndChar[i], 1), j + 1, ".WAV") = '\0'; - LevelMonsterTypes[monst].sounds[i][j] = sound_file_load(path); - } - } - } -} - -void FreeMonsterSnd() -{ -#ifdef _DEBUG - for (size_t i = 0; i < MaxLvlMTypes; i++) { -#else - for (size_t i = 0; i < LevelMonsterTypeCount; i++) { -#endif - for (auto &variants : LevelMonsterTypes[i].sounds) { - for (auto &snd : variants) { - snd = nullptr; - } - } - } -} - bool CalculateSoundPosition(Point soundPosition, int *plVolume, int *plPan) { const auto &playerPosition = MyPlayer->position.tile; diff --git a/Source/effects.h b/Source/effects.h index a5074cbac..06ec44007 100644 --- a/Source/effects.h +++ b/Source/effects.h @@ -1177,8 +1177,6 @@ extern _sfx_id sfxdnum; bool effect_is_playing(int nSFX); void stream_stop(); -void InitMonsterSND(size_t monst); -void FreeMonsterSnd(); bool CalculateSoundPosition(Point soundPosition, int *plVolume, int *plPan); void PlaySFX(_sfx_id psfx); void PlaySfxLoc(_sfx_id psfx, Point position, bool randomizeByCategory = true); diff --git a/Source/effects_stubs.cpp b/Source/effects_stubs.cpp index 08fc48f62..9dac30b1b 100644 --- a/Source/effects_stubs.cpp +++ b/Source/effects_stubs.cpp @@ -12,8 +12,6 @@ _sfx_id sfxdnum; // clang-format off bool effect_is_playing(int nSFX) { return false; } void stream_stop() { } -void InitMonsterSND(size_t monst) { } -void FreeMonsterSnd() { } bool CalculateSoundPosition(Point soundPosition, int *plVolume, int *plPan) { return false; } void PlaySFX(_sfx_id psfx) { diff --git a/Source/monstdat.cpp b/Source/monstdat.cpp index b049f1e11..be745a4f5 100644 --- a/Source/monstdat.cpp +++ b/Source/monstdat.cpp @@ -56,7 +56,7 @@ const MonsterData MonstersData[] = { /* MT_TSKELSD */ { P_("monster", "Corpse Captain"), "SkelSd\\SklSr", nullptr, "SkelSd\\Skelt", MonsterAvailability::Always, 128, 575, true, false, { 13, 8, 12, 7, 15, 16 }, { 4, 1, 1, 1, 1, 1 }, 2, 4, 4, 12, 20, AI_SKELSD, 0 , 1, 30, 8, 3, 9, 0, 0, 0, 0, 5, MonsterClass::Undead, IMMUNE_MAGIC | IMMUNE_NULL_40 , IMMUNE_MAGIC | IMMUNE_NULL_40 , 3, 0, 200 }, /* MT_RSKELSD */ { P_("monster", "Burning Dead Captain"), "SkelSd\\SklSr", nullptr, nullptr, MonsterAvailability::Always, 128, 575, true, false, { 13, 8, 12, 7, 15, 16 }, { 4, 1, 1, 1, 1, 1 }, 3, 5, 6, 16, 30, AI_SKELSD, 0 , 2, 35, 8, 4, 10, 0, 0, 0, 0, 15, MonsterClass::Undead, IMMUNE_MAGIC | RESIST_FIRE | IMMUNE_NULL_40 , IMMUNE_MAGIC | IMMUNE_FIRE | IMMUNE_NULL_40 , 3, 0, 393 }, /* MT_XSKELSD */ { P_("monster", "Horror Captain"), "SkelSd\\SklSr", nullptr, "SkelSd\\Black", MonsterAvailability::Always, 128, 575, true, false, { 13, 8, 12, 7, 15, 16 }, { 4, 1, 1, 1, 1, 1 }, 4, 6, 8, 35, 50, AI_SKELSD, MFLAG_SEARCH , 3, 40, 8, 5, 14, 0, 0, 0, 0, 30, MonsterClass::Undead, IMMUNE_MAGIC | RESIST_LIGHTNING | IMMUNE_NULL_40 , IMMUNE_MAGIC | RESIST_LIGHTNING | IMMUNE_NULL_40 , 3, 0, 604 }, -/* MT_INVILORD*/ { P_("monster", "Invisible Lord"), "TSneak\\TSneak", "TSneak\\Sneakl", nullptr, MonsterAvailability::Never, 128, 800, false, false, { 13, 13, 15, 11, 16, 0 }, { 2, 1, 1, 1, 1, 1 }, 19, 20, 14, 278, 278, AI_SKELSD, MFLAG_SEARCH | MFLAG_CAN_OPEN_DOOR, 3, 65, 8, 16, 30, 0, 0, 0, 0, 60, MonsterClass::Demon, RESIST_MAGIC | RESIST_FIRE | RESIST_LIGHTNING | IMMUNE_NULL_40 , RESIST_MAGIC | RESIST_FIRE | RESIST_LIGHTNING | IMMUNE_NULL_40 , 3, 0, 2000 }, +/* MT_INVILORD*/ { P_("monster", "Invisible Lord"), "TSneak\\TSneak", nullptr, nullptr, MonsterAvailability::Never, 128, 800, false, false, { 13, 13, 15, 11, 16, 0 }, { 2, 1, 1, 1, 1, 1 }, 19, 20, 14, 278, 278, AI_SKELSD, MFLAG_SEARCH | MFLAG_CAN_OPEN_DOOR, 3, 65, 8, 16, 30, 0, 0, 0, 0, 60, MonsterClass::Demon, RESIST_MAGIC | RESIST_FIRE | RESIST_LIGHTNING | IMMUNE_NULL_40 , RESIST_MAGIC | RESIST_FIRE | RESIST_LIGHTNING | IMMUNE_NULL_40 , 3, 0, 2000 }, /* MT_SNEAK */ { P_("monster", "Hidden"), "Sneak\\Sneak", nullptr, nullptr, MonsterAvailability::Retail, 128, 992, true, false, { 16, 8, 12, 8, 24, 15 }, { 2, 1, 1, 1, 1, 1 }, 2, 5, 5, 8, 24, AI_SNEAK, MFLAG_HIDDEN , 0, 35, 8, 3, 6, 0, 0, 0, 0, 25, MonsterClass::Demon, 0 , IMMUNE_NULL_40 , 3, 0, 278 }, /* MT_STALKER */ { P_("monster", "Stalker"), "Sneak\\Sneak", nullptr, "Sneak\\Sneakv2", MonsterAvailability::Retail, 128, 992, true, false, { 16, 8, 12, 8, 24, 15 }, { 2, 1, 1, 1, 1, 1 }, 5, 7, 9, 30, 45, AI_SNEAK, MFLAG_HIDDEN | MFLAG_SEARCH , 1, 40, 8, 8, 16, 0, 0, 0, 0, 30, MonsterClass::Demon, 0 , IMMUNE_NULL_40 , 3, 0, 630 }, /* MT_UNSEEN */ { P_("monster", "Unseen"), "Sneak\\Sneak", nullptr, "Sneak\\Sneakv3", MonsterAvailability::Retail, 128, 992, true, false, { 16, 8, 12, 8, 24, 15 }, { 2, 1, 1, 1, 1, 1 }, 6, 8, 11, 35, 50, AI_SNEAK, MFLAG_HIDDEN | MFLAG_SEARCH , 2, 45, 8, 12, 20, 0, 0, 0, 0, 30, MonsterClass::Demon, RESIST_MAGIC | IMMUNE_NULL_40 , IMMUNE_MAGIC | IMMUNE_NULL_40 , 3, 0, 935 }, @@ -84,10 +84,10 @@ const MonsterData MonstersData[] = { /* MT_MUDMAN, */ { P_("monster", "Mud Man"), "Fat\\Fat", nullptr, "Fat\\Blue", MonsterAvailability::Retail, 128, 1130, true, false, { 8, 10, 15, 6, 16, 10 }, { 4, 1, 1, 1, 1, 1 }, 7, 9, 14, 100, 125, AI_FAT, MFLAG_SEARCH , 1, 60, 8, 8, 16, 0, 0, 0, 0, 60, MonsterClass::Demon, 0 , IMMUNE_LIGHTNING , 3, 0, 1165 }, /* MT_TOAD */ { P_("monster", "Toad Demon"), "Fat\\Fat", nullptr, "Fat\\FatB", MonsterAvailability::Retail, 128, 1130, true, false, { 8, 10, 15, 6, 16, 10 }, { 4, 1, 1, 1, 1, 1 }, 8, 10, 16, 135, 160, AI_FAT, MFLAG_SEARCH , 2, 70, 8, 8, 16, 40, 0, 8, 20, 65, MonsterClass::Demon, IMMUNE_MAGIC , IMMUNE_MAGIC | RESIST_LIGHTNING , 3, 0, 1380 }, /* MT_FLAYED */ { P_("monster", "Flayed One"), "Fat\\Fat", nullptr, "Fat\\FatF", MonsterAvailability::Retail, 128, 1130, true, false, { 8, 10, 15, 6, 16, 10 }, { 4, 1, 1, 1, 1, 1 }, 10, 12, 20, 160, 200, AI_FAT, MFLAG_SEARCH , 3, 85, 8, 10, 20, 0, 0, 0, 0, 70, MonsterClass::Demon, RESIST_MAGIC | IMMUNE_FIRE , IMMUNE_MAGIC | IMMUNE_FIRE , 3, 0, 2058 }, -/* MT_WYRM */ { P_("monster", "Wyrm"), "Worm\\Worm", "Fat\\Fat", nullptr, MonsterAvailability::Never, 160, 2420, false, false, { 13, 13, 13, 11, 19, 0 }, { 1, 1, 1, 1, 1, 1 }, 5, 7, 11, 60, 90, AI_SKELSD, 0 , 0, 40, 8, 4, 10, 0, 0, 0, 0, 25, MonsterClass::Animal, RESIST_MAGIC , RESIST_MAGIC , 3, 0, 660 }, -/* MT_CAVSLUG */ { P_("monster", "Cave Slug"), "Worm\\Worm", "Fat\\Fat", nullptr, MonsterAvailability::Never, 160, 2420, false, false, { 13, 13, 13, 11, 19, 0 }, { 1, 1, 1, 1, 1, 1 }, 6, 8, 13, 75, 110, AI_SKELSD, 0 , 1, 50, 8, 6, 13, 0, 0, 0, 0, 30, MonsterClass::Animal, RESIST_MAGIC , RESIST_MAGIC , 3, 0, 994 }, -/* MT_DVLWYRM */ { P_("monster", "Devil Wyrm"), "Worm\\Worm", "Fat\\Fat", nullptr, MonsterAvailability::Never, 160, 2420, false, false, { 13, 13, 13, 11, 19, 0 }, { 1, 1, 1, 1, 1, 1 }, 7, 9, 15, 100, 140, AI_SKELSD, 0 , 2, 55, 8, 8, 16, 0, 0, 0, 0, 30, MonsterClass::Animal, RESIST_MAGIC | RESIST_FIRE , RESIST_MAGIC | RESIST_FIRE , 3, 0, 1320 }, -/* MT_DEVOUR */ { P_("monster", "Devourer"), "Worm\\Worm", "Fat\\Fat", nullptr, MonsterAvailability::Never, 160, 2420, false, false, { 13, 13, 13, 11, 19, 0 }, { 1, 1, 1, 1, 1, 1 }, 8, 10, 17, 125, 200, AI_SKELSD, 0 , 3, 60, 8, 10, 20, 0, 0, 0, 0, 35, MonsterClass::Animal, RESIST_MAGIC | RESIST_FIRE | IMMUNE_NULL_40 , RESIST_MAGIC | RESIST_FIRE | IMMUNE_NULL_40 , 3, 0, 1827 }, +/* MT_WYRM */ { P_("monster", "Wyrm"), "Worm\\Worm", nullptr, nullptr, MonsterAvailability::Never, 160, 2420, false, false, { 13, 13, 13, 11, 19, 0 }, { 1, 1, 1, 1, 1, 1 }, 5, 7, 11, 60, 90, AI_SKELSD, 0 , 0, 40, 8, 4, 10, 0, 0, 0, 0, 25, MonsterClass::Animal, RESIST_MAGIC , RESIST_MAGIC , 3, 0, 660 }, +/* MT_CAVSLUG */ { P_("monster", "Cave Slug"), "Worm\\Worm", nullptr, nullptr, MonsterAvailability::Never, 160, 2420, false, false, { 13, 13, 13, 11, 19, 0 }, { 1, 1, 1, 1, 1, 1 }, 6, 8, 13, 75, 110, AI_SKELSD, 0 , 1, 50, 8, 6, 13, 0, 0, 0, 0, 30, MonsterClass::Animal, RESIST_MAGIC , RESIST_MAGIC , 3, 0, 994 }, +/* MT_DVLWYRM */ { P_("monster", "Devil Wyrm"), "Worm\\Worm", nullptr, nullptr, MonsterAvailability::Never, 160, 2420, false, false, { 13, 13, 13, 11, 19, 0 }, { 1, 1, 1, 1, 1, 1 }, 7, 9, 15, 100, 140, AI_SKELSD, 0 , 2, 55, 8, 8, 16, 0, 0, 0, 0, 30, MonsterClass::Animal, RESIST_MAGIC | RESIST_FIRE , RESIST_MAGIC | RESIST_FIRE , 3, 0, 1320 }, +/* MT_DEVOUR */ { P_("monster", "Devourer"), "Worm\\Worm", nullptr, nullptr, MonsterAvailability::Never, 160, 2420, false, false, { 13, 13, 13, 11, 19, 0 }, { 1, 1, 1, 1, 1, 1 }, 8, 10, 17, 125, 200, AI_SKELSD, 0 , 3, 60, 8, 10, 20, 0, 0, 0, 0, 35, MonsterClass::Animal, RESIST_MAGIC | RESIST_FIRE | IMMUNE_NULL_40 , RESIST_MAGIC | RESIST_FIRE | IMMUNE_NULL_40 , 3, 0, 1827 }, /* MT_NMAGMA */ { P_("monster", "Magma Demon"), "Magma\\Magma", nullptr, nullptr, MonsterAvailability::Retail, 128, 1680, true, true, { 8, 10, 14, 7, 18, 18 }, { 2, 1, 1, 1, 1, 1 }, 8, 9, 13, 50, 70, AI_MAGMA, MFLAG_SEARCH | MFLAG_CAN_OPEN_DOOR, 0, 45, 4, 2, 10, 50, 13, 0, 0, 45, MonsterClass::Demon, IMMUNE_MAGIC | RESIST_FIRE , IMMUNE_MAGIC | IMMUNE_FIRE , 7, 0, 1076 }, /* MT_YMAGMA */ { P_("monster", "Blood Stone"), "Magma\\Magma", nullptr, "Magma\\Yellow", MonsterAvailability::Retail, 128, 1680, true, true, { 8, 10, 14, 7, 18, 18 }, { 2, 1, 1, 1, 1, 1 }, 8, 10, 14, 55, 75, AI_MAGMA, MFLAG_SEARCH | MFLAG_CAN_OPEN_DOOR, 1, 50, 4, 2, 12, 50, 14, 0, 0, 45, MonsterClass::Demon, IMMUNE_MAGIC | IMMUNE_FIRE , IMMUNE_MAGIC | IMMUNE_FIRE , 7, 0, 1309 }, /* MT_BMAGMA */ { P_("monster", "Hell Stone"), "Magma\\Magma", nullptr, "Magma\\Blue", MonsterAvailability::Retail, 128, 1680, true, true, { 8, 10, 14, 7, 18, 18 }, { 2, 1, 1, 1, 1, 1 }, 9, 11, 16, 60, 80, AI_MAGMA, MFLAG_SEARCH | MFLAG_CAN_OPEN_DOOR, 2, 60, 4, 2, 20, 60, 14, 0, 0, 50, MonsterClass::Demon, IMMUNE_MAGIC | IMMUNE_FIRE , IMMUNE_MAGIC | IMMUNE_FIRE , 7, 0, 1680 }, @@ -96,14 +96,14 @@ const MonsterData MonstersData[] = { /* MT_MUDRUN */ { P_("monster", "Mud Runner"), "Rhino\\Rhino", nullptr, "Rhino\\Orange", MonsterAvailability::Retail, 160, 1630, true, true, { 8, 8, 14, 6, 16, 6 }, { 2, 1, 1, 1, 1, 1 }, 8, 10, 15, 50, 90, AI_RHINO, MFLAG_SEARCH | MFLAG_CAN_OPEN_DOOR, 1, 70, 7, 6, 18, 100, 0, 12, 36, 45, MonsterClass::Animal, 0 , RESIST_FIRE , 7, 0, 1404 }, /* MT_FROSTC */ { P_("monster", "Frost Charger"), "Rhino\\Rhino", nullptr, "Rhino\\Blue", MonsterAvailability::Retail, 160, 1630, true, true, { 8, 8, 14, 6, 16, 6 }, { 2, 1, 1, 1, 1, 1 }, 9, 11, 17, 60, 100, AI_RHINO, MFLAG_SEARCH | MFLAG_CAN_OPEN_DOOR, 2, 80, 7, 8, 20, 100, 0, 20, 40, 50, MonsterClass::Animal, IMMUNE_MAGIC | RESIST_LIGHTNING , IMMUNE_MAGIC | RESIST_LIGHTNING , 7, 0, 1720 }, /* MT_OBLORD */ { P_("monster", "Obsidian Lord"), "Rhino\\Rhino", nullptr, "Rhino\\RhinoB", MonsterAvailability::Retail, 160, 1630, true, true, { 8, 8, 14, 6, 16, 6 }, { 2, 1, 1, 1, 1, 1 }, 10, 12, 19, 70, 110, AI_RHINO, MFLAG_SEARCH | MFLAG_CAN_OPEN_DOOR, 3, 90, 7, 10, 22, 100, 0, 20, 50, 55, MonsterClass::Animal, IMMUNE_MAGIC | RESIST_LIGHTNING , IMMUNE_MAGIC | IMMUNE_FIRE | IMMUNE_LIGHTNING , 7, 0, 1809 }, -/* MT_BONEDMN */ { P_("monster", "oldboned"), "Demskel\\Demskl", "Thin\\Thin", nullptr, MonsterAvailability::Never, 128, 1740, true, true, { 10, 8, 20, 6, 24, 16 }, { 3, 1, 1, 1, 1, 1 }, 24, 24, 12, 70, 70, AI_STORM, 0 , 0, 60, 8, 6, 14, 12, 0, 0, 0, 50, MonsterClass::Demon, IMMUNE_MAGIC | IMMUNE_NULL_40 , IMMUNE_MAGIC | IMMUNE_NULL_40 , 7, 0, 1344 }, +/* MT_BONEDMN */ { P_("monster", "oldboned"), "Demskel\\Demskl", nullptr, nullptr, MonsterAvailability::Never, 128, 1740, true, true, { 10, 8, 20, 6, 24, 16 }, { 3, 1, 1, 1, 1, 1 }, 24, 24, 12, 70, 70, AI_STORM, 0 , 0, 60, 8, 6, 14, 12, 0, 0, 0, 50, MonsterClass::Demon, IMMUNE_MAGIC | IMMUNE_NULL_40 , IMMUNE_MAGIC | IMMUNE_NULL_40 , 7, 0, 1344 }, /* MT_REDDTH */ { P_("monster", "Red Death"), "Thin\\Thin", nullptr, "Thin\\Thinv3", MonsterAvailability::Never, 160, 1740, true, true, { 8, 8, 18, 4, 17, 14 }, { 3, 1, 1, 1, 1, 1 }, 8, 10, 16, 96, 96, AI_STORM, 0 , 1, 75, 5, 10, 20, 0, 0, 0, 0, 60, MonsterClass::Demon, IMMUNE_MAGIC | IMMUNE_FIRE , IMMUNE_MAGIC | IMMUNE_FIRE , 7, 0, 2168 }, /* MT_LTCHDMN */ { P_("monster", "Litch Demon"), "Thin\\Thin", nullptr, "Thin\\Thinv3", MonsterAvailability::Never, 160, 1740, true, true, { 8, 8, 18, 4, 17, 14 }, { 3, 1, 1, 1, 1, 1 }, 9, 11, 18, 110, 110, AI_STORM, 0 , 2, 80, 5, 10, 24, 0, 0, 0, 0, 45, MonsterClass::Demon, IMMUNE_MAGIC | IMMUNE_LIGHTNING | IMMUNE_NULL_40 , IMMUNE_MAGIC | IMMUNE_LIGHTNING | IMMUNE_NULL_40 , 7, 0, 2736 }, /* MT_UDEDBLRG*/ { P_("monster", "Undead Balrog"), "Thin\\Thin", nullptr, "Thin\\Thinv3", MonsterAvailability::Never, 160, 1740, true, true, { 8, 8, 18, 4, 17, 14 }, { 3, 1, 1, 1, 1, 1 }, 11, 13, 22, 130, 130, AI_STORM, 0 , 3, 85, 5, 12, 30, 0, 0, 0, 0, 65, MonsterClass::Demon, IMMUNE_MAGIC | RESIST_FIRE | RESIST_LIGHTNING | IMMUNE_NULL_40 , IMMUNE_MAGIC | RESIST_FIRE | RESIST_LIGHTNING | IMMUNE_NULL_40 , 7, 0, 3575 }, -/* MT_INCIN */ { P_("monster", "Incinerator"), "Fireman\\FireM", "Acid\\Acid", nullptr, MonsterAvailability::Never, 128, 1460, true, false, { 14, 19, 20, 8, 14, 23 }, { 1, 1, 1, 1, 1, 1 }, 21, 22, 16, 30, 45, AI_FIREMAN, 0 , 0, 75, 8, 8, 16, 0, 0, 0, 0, 25, MonsterClass::Demon, IMMUNE_MAGIC | IMMUNE_FIRE , IMMUNE_MAGIC | IMMUNE_FIRE , 3, 0, 1888 }, -/* MT_FLAMLRD */ { P_("monster", "Flame Lord"), "Fireman\\FireM", "Acid\\Acid", nullptr, MonsterAvailability::Never, 128, 1460, true, false, { 14, 19, 20, 8, 14, 23 }, { 1, 1, 1, 1, 1, 1 }, 22, 23, 18, 40, 55, AI_FIREMAN, 0 , 1, 75, 8, 10, 20, 0, 0, 0, 0, 25, MonsterClass::Demon, IMMUNE_MAGIC | IMMUNE_FIRE , IMMUNE_MAGIC | IMMUNE_FIRE , 3, 0, 2250 }, -/* MT_DOOMFIRE*/ { P_("monster", "Doom Fire"), "Fireman\\FireM", "Acid\\Acid", nullptr, MonsterAvailability::Never, 128, 1460, true, false, { 14, 19, 20, 8, 14, 23 }, { 1, 1, 1, 1, 1, 1 }, 23, 24, 20, 50, 65, AI_FIREMAN, 0 , 2, 80, 8, 12, 24, 0, 0, 0, 0, 30, MonsterClass::Demon, IMMUNE_MAGIC | IMMUNE_FIRE | RESIST_LIGHTNING , IMMUNE_MAGIC | IMMUNE_FIRE | RESIST_LIGHTNING , 3, 0, 2740 }, -/* MT_HELLBURN*/ { P_("monster", "Hell Burner"), "Fireman\\FireM", "Acid\\Acid", nullptr, MonsterAvailability::Never, 128, 1460, true, false, { 14, 19, 20, 8, 14, 23 }, { 1, 1, 1, 1, 1, 1 }, 24, 24, 22, 60, 80, AI_FIREMAN, 0 , 3, 85, 8, 15, 30, 0, 0, 0, 0, 30, MonsterClass::Demon, IMMUNE_MAGIC | IMMUNE_FIRE | RESIST_LIGHTNING , IMMUNE_MAGIC | IMMUNE_FIRE | RESIST_LIGHTNING , 3, 0, 3355 }, +/* MT_INCIN */ { P_("monster", "Incinerator"), "Fireman\\FireM", nullptr, nullptr, MonsterAvailability::Never, 128, 1460, true, false, { 14, 19, 20, 8, 14, 23 }, { 1, 1, 1, 1, 1, 1 }, 21, 22, 16, 30, 45, AI_FIREMAN, 0 , 0, 75, 8, 8, 16, 0, 0, 0, 0, 25, MonsterClass::Demon, IMMUNE_MAGIC | IMMUNE_FIRE , IMMUNE_MAGIC | IMMUNE_FIRE , 3, 0, 1888 }, +/* MT_FLAMLRD */ { P_("monster", "Flame Lord"), "Fireman\\FireM", nullptr, nullptr, MonsterAvailability::Never, 128, 1460, true, false, { 14, 19, 20, 8, 14, 23 }, { 1, 1, 1, 1, 1, 1 }, 22, 23, 18, 40, 55, AI_FIREMAN, 0 , 1, 75, 8, 10, 20, 0, 0, 0, 0, 25, MonsterClass::Demon, IMMUNE_MAGIC | IMMUNE_FIRE , IMMUNE_MAGIC | IMMUNE_FIRE , 3, 0, 2250 }, +/* MT_DOOMFIRE*/ { P_("monster", "Doom Fire"), "Fireman\\FireM", nullptr, nullptr, MonsterAvailability::Never, 128, 1460, true, false, { 14, 19, 20, 8, 14, 23 }, { 1, 1, 1, 1, 1, 1 }, 23, 24, 20, 50, 65, AI_FIREMAN, 0 , 2, 80, 8, 12, 24, 0, 0, 0, 0, 30, MonsterClass::Demon, IMMUNE_MAGIC | IMMUNE_FIRE | RESIST_LIGHTNING , IMMUNE_MAGIC | IMMUNE_FIRE | RESIST_LIGHTNING , 3, 0, 2740 }, +/* MT_HELLBURN*/ { P_("monster", "Hell Burner"), "Fireman\\FireM", nullptr, nullptr, MonsterAvailability::Never, 128, 1460, true, false, { 14, 19, 20, 8, 14, 23 }, { 1, 1, 1, 1, 1, 1 }, 24, 24, 22, 60, 80, AI_FIREMAN, 0 , 3, 85, 8, 15, 30, 0, 0, 0, 0, 30, MonsterClass::Demon, IMMUNE_MAGIC | IMMUNE_FIRE | RESIST_LIGHTNING , IMMUNE_MAGIC | IMMUNE_FIRE | RESIST_LIGHTNING , 3, 0, 3355 }, /* MT_STORM */ { P_("monster", "Red Storm"), "Thin\\Thin", nullptr, "Thin\\Thinv3", MonsterAvailability::Retail, 160, 1740, true, true, { 8, 8, 18, 4, 17, 14 }, { 3, 1, 1, 1, 1, 1 }, 9, 11, 18, 55, 110, AI_STORM, MFLAG_SEARCH | MFLAG_CAN_OPEN_DOOR, 0, 80, 5, 8, 18, 75, 8, 4, 16, 30, MonsterClass::Demon, IMMUNE_MAGIC | RESIST_LIGHTNING , IMMUNE_MAGIC | IMMUNE_LIGHTNING , 7, 0, 2160 }, /* MT_RSTORM */ { P_("monster", "Storm Rider"), "Thin\\Thin", nullptr, nullptr, MonsterAvailability::Retail, 160, 1740, true, true, { 8, 8, 18, 4, 17, 14 }, { 3, 1, 1, 1, 1, 1 }, 10, 12, 20, 60, 120, AI_STORM, MFLAG_SEARCH | MFLAG_CAN_OPEN_DOOR, 1, 80, 5, 8, 18, 80, 8, 4, 16, 30, MonsterClass::Demon, RESIST_MAGIC | IMMUNE_LIGHTNING , IMMUNE_MAGIC | IMMUNE_LIGHTNING , 7, 0, 2391 }, /* MT_STORML */ { P_("monster", "Storm Lord"), "Thin\\Thin", nullptr, "Thin\\Thinv2", MonsterAvailability::Retail, 160, 1740, true, true, { 8, 8, 18, 4, 17, 14 }, { 3, 1, 1, 1, 1, 1 }, 11, 13, 22, 75, 135, AI_STORM, MFLAG_SEARCH | MFLAG_CAN_OPEN_DOOR, 2, 85, 5, 12, 24, 75, 8, 4, 16, 35, MonsterClass::Demon, RESIST_MAGIC | IMMUNE_LIGHTNING , IMMUNE_MAGIC | IMMUNE_LIGHTNING , 7, 0, 2775 }, diff --git a/Source/monster.cpp b/Source/monster.cpp index 900d2eded..ef6fe1830 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -179,8 +179,8 @@ void InitMonsterTRN(CMonster &monst) AnimStruct &anim = monst.anims[i]; if (IsDirectionalAnim(monst, i)) { - for (size_t j = 0; j < 8; ++j) { - Cl2ApplyTrans(anim.celSpritesForDirections[j], colorTranslations, anim.frames); + for (size_t i = 0; i < 8; i++) { + Cl2ApplyTrans(anim.celSpritesForDirections[i], colorTranslations, anim.frames); } } else { byte *frames[8]; @@ -192,13 +192,13 @@ void InitMonsterTRN(CMonster &monst) } } -void InitMonster(Monster &monster, Direction rd, int mtype, Point position) +void InitMonster(Monster &monster, Direction rd, size_t typeIndex, Point position) { monster.direction = rd; monster.position.tile = position; monster.position.future = position; monster.position.old = position; - monster.levelType = mtype; + monster.levelType = typeIndex; monster.mode = MonsterMode::Stand; monster.animInfo = {}; monster.changeAnimationData(MonsterGraphic::Stand); @@ -298,14 +298,11 @@ bool CanPlaceMonster(Point position) && !IsTileOccupied(position); } -void PlaceMonster(int i, int mtype, Point position) +void PlaceMonster(int i, size_t typeIndex, Point position) { - if (LevelMonsterTypes[mtype].type == MT_NAKRUL) { + if (LevelMonsterTypes[typeIndex].type == MT_NAKRUL) { for (size_t j = 0; j < ActiveMonsterCount; j++) { - if (Monsters[j].levelType == mtype) { - return; - } - if (Monsters[j].type().type == MT_NAKRUL) { + if (Monsters[j].levelType == typeIndex) { return; } } @@ -313,10 +310,10 @@ void PlaceMonster(int i, int mtype, Point position) dMonster[position.x][position.y] = i + 1; auto rd = static_cast(GenerateRnd(8)); - InitMonster(Monsters[i], rd, mtype, position); + InitMonster(Monsters[i], rd, typeIndex, position); } -void PlaceGroup(int mtype, unsigned num, Monster *leader = nullptr, bool leashed = false) +void PlaceGroup(size_t typeIndex, unsigned num, Monster *leader = nullptr, bool leashed = false) { unsigned placed = 0; @@ -357,7 +354,7 @@ void PlaceGroup(int mtype, unsigned num, Monster *leader = nullptr, bool leashed continue; } - PlaceMonster(ActiveMonsterCount, mtype, { xp, yp }); + PlaceMonster(ActiveMonsterCount, typeIndex, { xp, yp }); if (leader != nullptr) { auto &minion = Monsters[ActiveMonsterCount]; minion.maxHitPoints *= 2; @@ -390,18 +387,20 @@ void PlaceGroup(int mtype, unsigned num, Monster *leader = nullptr, bool leashed } } -void PlaceUniqueMonst(UniqueMonsterType uniqindex, int miniontype, int bosspacksize) +size_t GetMonsterTypeIndex(_monster_id type) +{ + for (size_t i = 0; i < LevelMonsterTypeCount; i++) { + if (LevelMonsterTypes[i].type == type) + return i; + } + return LevelMonsterTypeCount; +} + +void PlaceUniqueMonst(UniqueMonsterType uniqindex, size_t minionType, int bosspacksize) { auto &monster = Monsters[ActiveMonsterCount]; const auto &uniqueMonsterData = UniqueMonstersData[static_cast(uniqindex)]; - size_t uniqtype; - for (uniqtype = 0; uniqtype < LevelMonsterTypeCount; uniqtype++) { - if (LevelMonsterTypes[uniqtype].type == uniqueMonsterData.mtype) { - break; - } - } - int count = 0; Point position; while (true) { @@ -477,45 +476,33 @@ void PlaceUniqueMonst(UniqueMonsterType uniqindex, int miniontype, int bosspacks position = { UberRow - 2, UberCol }; UberDiabloMonsterIndex = static_cast(ActiveMonsterCount); } - PlaceMonster(ActiveMonsterCount, uniqtype, position); + const size_t typeIndex = GetMonsterTypeIndex(uniqueMonsterData.mtype); + PlaceMonster(ActiveMonsterCount, typeIndex, position); ActiveMonsterCount++; - PrepareUniqueMonst(monster, uniqindex, miniontype, bosspacksize, uniqueMonsterData); -} - -size_t GetMonsterTypeIndex(_monster_id type) -{ - for (size_t i = 0; i < LevelMonsterTypeCount; i++) { - if (LevelMonsterTypes[i].type == type) - return i; - } - return LevelMonsterTypeCount; + PrepareUniqueMonst(monster, uniqindex, minionType, bosspacksize, uniqueMonsterData); } size_t AddMonsterType(_monster_id type, placeflag placeflag) { const size_t typeIndex = GetMonsterTypeIndex(type); + CMonster &monsterType = LevelMonsterTypes[typeIndex]; if (typeIndex == LevelMonsterTypeCount) { LevelMonsterTypeCount++; - LevelMonsterTypes[typeIndex].type = type; + monsterType.type = type; monstimgtot += MonstersData[type].image; - InitMonsterGFX(typeIndex); - InitMonsterSND(typeIndex); + InitMonsterGFX(monsterType); + InitMonsterSND(monsterType); } - LevelMonsterTypes[typeIndex].placeFlags |= placeflag; + monsterType.placeFlags |= placeflag; return typeIndex; } -inline _monster_id GetMonsterTypeFrom(UniqueMonsterType uniqueType) -{ - return UniqueMonstersData[static_cast(uniqueType)].mtype; -} - inline size_t AddMonsterType(UniqueMonsterType uniqueType, placeflag placeflag) { - return AddMonsterType(GetMonsterTypeFrom(uniqueType), placeflag); + return AddMonsterType(UniqueMonstersData[static_cast(uniqueType)].mtype, placeflag); } void ClearMVars(Monster &monster) @@ -554,8 +541,8 @@ void PlaceUniqueMonsters() if (UniqueMonstersData[u].mlevel != currlevel) continue; - const size_t mt = GetMonsterTypeIndex(UniqueMonstersData[u].mtype); - if (mt == LevelMonsterTypeCount) + const size_t minionType = GetMonsterTypeIndex(UniqueMonstersData[u].mtype); + if (minionType == LevelMonsterTypeCount) continue; UniqueMonsterType uniqueType = static_cast(u); @@ -570,7 +557,7 @@ void PlaceUniqueMonsters() if (uniqueType == UniqueMonsterType::WarlordOfBlood && Quests[Q_WARLORD]._qactive == QUEST_NOTAVAIL) continue; - PlaceUniqueMonst(uniqueType, mt, 8); + PlaceUniqueMonst(uniqueType, minionType, 8); } } @@ -630,17 +617,12 @@ void PlaceQuestMonsters() if (currlevel == 24) { UberDiabloMonsterIndex = -1; - size_t i1; - for (i1 = 0; i1 < LevelMonsterTypeCount; i1++) { - if (LevelMonsterTypes[i1].type == GetMonsterTypeFrom(UniqueMonsterType::NaKrul)) - break; - } - - if (i1 < LevelMonsterTypeCount) { - for (size_t i2 = 0; i2 < ActiveMonsterCount; i2++) { - auto &monster = Monsters[i2]; - if (monster.isUnique() || monster.levelType == i1) { - UberDiabloMonsterIndex = static_cast(i2); + const size_t typeIndex = GetMonsterTypeIndex(MT_NAKRUL); + if (typeIndex < LevelMonsterTypeCount) { + for (size_t i = 0; i < ActiveMonsterCount; i++) { + Monster &monster = Monsters[i]; + if (monster.isUnique() || monster.levelType == typeIndex) { + UberDiabloMonsterIndex = static_cast(i); break; } } @@ -738,9 +720,9 @@ void UpdateEnemy(Monster &monster) } } } - for (size_t j = 0; j < ActiveMonsterCount; j++) { - int mi = ActiveMonsters[j]; - auto &otherMonster = Monsters[mi]; + for (size_t i = 0; i < ActiveMonsterCount; i++) { + int monsterId = ActiveMonsters[i]; + auto &otherMonster = Monsters[monsterId]; if (&otherMonster == &monster) continue; if ((otherMonster.hitPoints >> 6) <= 0) @@ -768,7 +750,7 @@ void UpdateEnemy(Monster &monster) || ((sameroom || !bestsameroom) && dist < bestDist) || (menemy == -1)) { monster.flags |= MFLAG_TARGETS_MONSTER; - menemy = mi; + menemy = monsterId; target = otherMonster.position.future; bestDist = dist; bestsameroom = sameroom; @@ -949,9 +931,9 @@ void DiabloDeath(Monster &diablo, bool sendmsg) NetSendCmdQuest(true, quest); sgbSaveSoundOn = gbSoundOn; gbProcessPlayers = false; - for (size_t j = 0; j < ActiveMonsterCount; j++) { - int k = ActiveMonsters[j]; - auto &monster = Monsters[k]; + for (size_t i = 0; i < ActiveMonsterCount; i++) { + int monsterId = ActiveMonsters[i]; + Monster &monster = Monsters[monsterId]; if (monster.type().type == MT_DIABLO || diablo.activeForTicks == 0) continue; @@ -962,7 +944,7 @@ void DiabloDeath(Monster &diablo, bool sendmsg) monster.position.tile = monster.position.old; monster.position.future = monster.position.tile; M_ClearSquares(monster); - dMonster[monster.position.tile.x][monster.position.tile.y] = k + 1; + dMonster[monster.position.tile.x][monster.position.tile.y] = monsterId + 1; } AddLight(diablo.position.tile, 8); DoVision(diablo.position.tile, 8, MAP_EXP_NONE, true); @@ -1656,8 +1638,8 @@ bool MonsterGotHit(Monster &monster) void ReleaseMinions(const Monster &leader) { - for (size_t j = 0; j < ActiveMonsterCount; j++) { - auto &minion = Monsters[ActiveMonsters[j]]; + for (size_t i = 0; i < ActiveMonsterCount; i++) { + auto &minion = Monsters[ActiveMonsters[i]]; if (minion.leaderRelation == LeaderRelation::Leashed && minion.getLeader() == &leader) { minion.setLeader(nullptr); } @@ -1743,23 +1725,20 @@ void MonsterPetrified(Monster &monster) Monster *AddSkeleton(Point position, Direction dir, bool inMap) { - int j = 0; + size_t typeCount = 0; + size_t skeletonIndexes[sizeof(SkeletonTypes) / sizeof(SkeletonTypes[0])]; for (size_t i = 0; i < LevelMonsterTypeCount; i++) { - if (IsSkel(LevelMonsterTypes[i].type)) - j++; + if (IsSkel(LevelMonsterTypes[i].type)) { + skeletonIndexes[typeCount++] = i; + } } - if (j == 0) { + if (typeCount == 0) { return nullptr; } - int skeltypes = GenerateRnd(j); - size_t m = 0; - for (int i = 0; m < LevelMonsterTypeCount && i <= skeltypes; m++) { - if (IsSkel(LevelMonsterTypes[m].type)) - i++; - } - return AddMonster(position, dir, m - 1, inMap); + const size_t typeIndex = skeletonIndexes[GenerateRnd(typeCount)]; + return AddMonster(position, dir, typeIndex, inMap); } void SpawnSkeleton(Point position, Direction dir) @@ -3383,7 +3362,7 @@ void InitTRNForUniqueMonster(Monster &monster) monster.uniqueMonsterTRN = LoadFileInMem(filestr); } -void PrepareUniqueMonst(Monster &monster, UniqueMonsterType monsterType, int miniontype, int bosspacksize, const UniqueMonsterData &uniqueMonsterData) +void PrepareUniqueMonst(Monster &monster, UniqueMonsterType monsterType, size_t minionType, int bosspacksize, const UniqueMonsterData &uniqueMonsterData) { monster.uniqueType = monsterType; @@ -3479,7 +3458,7 @@ void PrepareUniqueMonst(Monster &monster, UniqueMonsterType monsterType, int min } if (uniqueMonsterData.monsterPack != UniqueMonsterPack::None) { - PlaceGroup(miniontype, bosspacksize, &monster, uniqueMonsterData.monsterPack == UniqueMonsterPack::Leashed); + PlaceGroup(minionType, bosspacksize, &monster, uniqueMonsterData.monsterPack == UniqueMonsterPack::Leashed); } if (monster.ai != AI_GARG) { @@ -3495,7 +3474,7 @@ void InitLevelMonsters() LevelMonsterTypeCount = 0; monstimgtot = 0; - for (auto &levelMonsterType : LevelMonsterTypes) { + for (CMonster &levelMonsterType : LevelMonsterTypes) { levelMonsterType.placeFlags = 0; } @@ -3595,10 +3574,37 @@ void GetLevelMTypes() } } -void InitMonsterGFX(size_t monsterTypeIndex) +void InitMonsterSND(CMonster &monsterType) { - CMonster &monster = LevelMonsterTypes[monsterTypeIndex]; - const _monster_id mtype = monster.type; + if (!gbSndInited) + return; + + const char *prefixes[] { + "a", // Attack + "h", // Hit + "d", // Death + "s", // Special + }; + + const MonsterData &data = MonstersData[monsterType.type]; + string_view soundSuffix = data.soundSuffix != nullptr ? data.soundSuffix : data.assetsSuffix; + + for (int i = 0; i < 4; i++) { + string_view prefix = prefixes[i]; + if (prefix == "s" && !data.hasSpecialSound) + continue; + + for (int j = 0; j < 2; j++) { + char path[MAX_PATH]; + *BufCopy(path, "Monsters\\", soundSuffix, prefix, j + 1, ".WAV") = '\0'; + monsterType.sounds[i][j] = sound_file_load(path); + } + } +} + +void InitMonsterGFX(CMonster &monsterType) +{ + const _monster_id mtype = monsterType.type; const MonsterData &monsterData = MonstersData[mtype]; const int width = monsterData.width; constexpr size_t MaxAnims = sizeof(Animletter) / sizeof(Animletter[0]) - 1; @@ -3610,7 +3616,7 @@ void InitMonsterGFX(size_t monsterTypeIndex) std::array animOffsets; if (!HeadlessMode) { - monster.animData = MultiFileLoader {}( + monsterType.animData = MultiFileLoader {}( numAnims, FileNameWithCharAffixGenerator({ "Monsters\\", monsterData.assetsSuffix }, ".CL2", Animletter), animOffsets.data(), @@ -3618,7 +3624,7 @@ void InitMonsterGFX(size_t monsterTypeIndex) } for (unsigned animIndex = 0; animIndex < numAnims; animIndex++) { - AnimStruct &anim = monster.anims[animIndex]; + AnimStruct &anim = monsterType.anims[animIndex]; if (!hasAnim(animIndex)) { anim.frames = 0; @@ -3632,8 +3638,8 @@ void InitMonsterGFX(size_t monsterTypeIndex) if (HeadlessMode) continue; - byte *cl2Data = &monster.animData[animOffsets[animIndex]]; - if (IsDirectionalAnim(monster, animIndex)) { + byte *cl2Data = &monsterType.animData[animOffsets[animIndex]]; + if (IsDirectionalAnim(monsterType, animIndex)) { CelGetDirectionFrames(cl2Data, anim.celSpritesForDirections.data()); } else { for (size_t i = 0; i < 8; ++i) { @@ -3642,13 +3648,13 @@ void InitMonsterGFX(size_t monsterTypeIndex) } } - monster.data = &monsterData; + monsterType.data = &monsterData; if (HeadlessMode) return; if (monsterData.trnFile != nullptr) { - InitMonsterTRN(monster); + InitMonsterTRN(monsterType); } if (IsAnyOf(mtype, MT_NMAGMA, MT_YMAGMA, MT_BMAGMA, MT_WMAGMA)) @@ -3750,7 +3756,7 @@ void InitMonsters() numplacemonsters = MaxMonsters - 10 - ActiveMonsterCount; totalmonsters = ActiveMonsterCount + numplacemonsters; int numscattypes = 0; - int scattertypes[NUM_MTYPES]; + size_t scattertypes[NUM_MTYPES]; for (size_t i = 0; i < LevelMonsterTypeCount; i++) { if ((LevelMonsterTypes[i].placeFlags & PLACE_SCATTER) != 0) { scattertypes[numscattypes] = i; @@ -3758,14 +3764,14 @@ void InitMonsters() } } while (ActiveMonsterCount < totalmonsters) { - int mtype = scattertypes[GenerateRnd(numscattypes)]; + const size_t typeIndex = scattertypes[GenerateRnd(numscattypes)]; if (currlevel == 1 || FlipCoin()) na = 1; else if (currlevel == 2 || leveltype == DTYPE_CRYPT) na = GenerateRnd(2) + 2; else na = GenerateRnd(3) + 3; - PlaceGroup(mtype, na); + PlaceGroup(typeIndex, na); } } for (int i = 0; i < nt; i++) { @@ -3807,20 +3813,20 @@ void SetMapMonsters(const uint16_t *dunData, Point startPosition) for (int i = 0; i < width; i++) { auto monsterId = static_cast(SDL_SwapLE16(monsterLayer[j * width + i])); if (monsterId != 0) { - const size_t mtype = AddMonsterType(MonstConvTbl[monsterId - 1], PLACE_SPECIAL); - PlaceMonster(ActiveMonsterCount++, mtype, startPosition + Displacement { i, j }); + const size_t typeIndex = AddMonsterType(MonstConvTbl[monsterId - 1], PLACE_SPECIAL); + PlaceMonster(ActiveMonsterCount++, typeIndex, startPosition + Displacement { i, j }); } } } } -Monster *AddMonster(Point position, Direction dir, size_t mtype, bool inMap) +Monster *AddMonster(Point position, Direction dir, size_t typeIndex, bool inMap) { if (ActiveMonsterCount < MaxMonsters) { Monster &monster = Monsters[ActiveMonsters[ActiveMonsterCount++]]; if (inMap) dMonster[position.x][position.y] = monster.getId() + 1; - InitMonster(monster, dir, mtype, position); + InitMonster(monster, dir, typeIndex, position); return &monster; } @@ -3837,12 +3843,8 @@ void AddDoppelganger(Monster &monster) target = position; } if (target != Point { 0, 0 }) { - for (size_t j = 0; j < MaxLvlMTypes; j++) { - if (LevelMonsterTypes[j].type == monster.type().type) { - AddMonster(target, monster.direction, j, true); - break; - } - } + const size_t typeIndex = GetMonsterTypeIndex(monster.type().type); + AddMonster(target, monster.direction, typeIndex, true); } } @@ -4236,8 +4238,14 @@ void ProcessMonsters() void FreeMonsters() { - for (size_t i = 0; i < LevelMonsterTypeCount; i++) { - LevelMonsterTypes[i].animData = nullptr; + for (CMonster &monsterType : LevelMonsterTypes) { + monsterType.animData = nullptr; + + for (auto &variants : monsterType.sounds) { + for (auto &sound : variants) { + sound = nullptr; + } + } } } @@ -4358,9 +4366,10 @@ void SyncMonsterAnim(Monster &monster) { #ifdef _DEBUG // fix for saves with debug monsters having type originally not on the level - if (LevelMonsterTypes[monster.levelType].data == nullptr) { - InitMonsterGFX(monster.levelType); - LevelMonsterTypes[monster.levelType].corpseId = 1; + CMonster &monsterType = LevelMonsterTypes[monster.levelType]; + if (monsterType.data == nullptr) { + InitMonsterGFX(monsterType); + monsterType.corpseId = 1; } #endif if (monster.isUnique()) { @@ -4531,8 +4540,7 @@ void PlayEffect(Monster &monster, int mode) return; } - int mi = monster.levelType; - TSnd *snd = LevelMonsterTypes[mi].sounds[mode][sndIdx].get(); + TSnd *snd = monster.type().sounds[mode][sndIdx].get(); if (snd == nullptr || snd->isPlaying()) { return; } diff --git a/Source/monster.h b/Source/monster.h index 3a0898add..5763e175d 100644 --- a/Source/monster.h +++ b/Source/monster.h @@ -354,10 +354,11 @@ extern size_t ActiveMonsterCount; extern int MonsterKillCounts[MaxMonsters]; extern bool sgbSaveSoundOn; -void PrepareUniqueMonst(Monster &monster, UniqueMonsterType monsterType, int miniontype, int bosspacksize, const UniqueMonsterData &uniqueMonsterData); +void PrepareUniqueMonst(Monster &monster, UniqueMonsterType monsterType, size_t miniontype, int bosspacksize, const UniqueMonsterData &uniqueMonsterData); void InitLevelMonsters(); void GetLevelMTypes(); -void InitMonsterGFX(size_t monsterTypeIndex); +void InitMonsterSND(CMonster &monsterType); +void InitMonsterGFX(CMonster &monsterType); void WeakenNaKrul(); void InitGolems(); void InitMonsters();