Browse Source

Clean up LevelMonsterTypes related code

pull/5008/head
Anders Jenbo 4 years ago
parent
commit
16b65120ea
  1. 9
      Source/dead.cpp
  2. 22
      Source/debug.cpp
  3. 1
      Source/diablo.cpp
  4. 44
      Source/effects.cpp
  5. 2
      Source/effects.h
  6. 2
      Source/effects_stubs.cpp
  7. 20
      Source/monstdat.cpp
  8. 226
      Source/monster.cpp
  9. 5
      Source/monster.h

9
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

22
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;

1
Source/diablo.cpp

@ -1712,7 +1712,6 @@ void FreeGameMem()
FreeMonsters();
FreeMissileGFX();
FreeObjectGFX();
FreeMonsterSnd();
FreeTownerGFX();
#ifndef USE_SDL1
DeactivateVirtualGamepad();

44
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;

2
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);

2
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)
{

20
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 },

226
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<Direction>(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<size_t>(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<int>(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<size_t>(uniqueType)].mtype;
}
inline size_t AddMonsterType(UniqueMonsterType uniqueType, placeflag placeflag)
{
return AddMonsterType(GetMonsterTypeFrom(uniqueType), placeflag);
return AddMonsterType(UniqueMonstersData[static_cast<size_t>(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<UniqueMonsterType>(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<int>(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<int>(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<uint8_t>(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<uint32_t, MaxAnims> animOffsets;
if (!HeadlessMode) {
monster.animData = MultiFileLoader<MaxAnims> {}(
monsterType.animData = MultiFileLoader<MaxAnims> {}(
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<uint8_t>(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;
}

5
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();

Loading…
Cancel
Save