diff --git a/Source/loadsave.cpp b/Source/loadsave.cpp index 128b48bc4..73d2c7684 100644 --- a/Source/loadsave.cpp +++ b/Source/loadsave.cpp @@ -669,6 +669,9 @@ void LoadMonster(LoadHelper *file, Monster &monster) // Omit pointer name; + if (monster.mode == MonsterMode::Petrified) + monster.animInfo.isPetrified = true; + if (gbSkipSync) return; diff --git a/Source/missiles.cpp b/Source/missiles.cpp index 690890d7f..2949e3bf1 100644 --- a/Source/missiles.cpp +++ b/Source/missiles.cpp @@ -2296,6 +2296,13 @@ void AddStoneCurse(Missile &missile, AddMissileParameter ¶meter) // Petrify the targeted monster int monsterId = abs(dMonster[targetMonsterPosition->x][targetMonsterPosition->y]) - 1; auto &monster = Monsters[monsterId]; + + if (monster.mode == MonsterMode::Petrified) { + // Monster is already petrified and StoneCurse doesn't stack + missile._miDelFlag = true; + return; + } + missile.var1 = static_cast(monster.mode); missile.var2 = monsterId; monster.petrify(); diff --git a/Source/monster.cpp b/Source/monster.cpp index 312787414..166d9fa81 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -4146,7 +4146,7 @@ void SyncMonsterAnim(Monster &monster) } MonsterGraphic graphic = MonsterGraphic::Stand; - switch (monster.mode) { + switch (monster.getVisualMonsterMode()) { case MonsterMode::Stand: case MonsterMode::Delay: case MonsterMode::Talk: @@ -4637,7 +4637,7 @@ void Monster::petrify() bool Monster::isWalking() const { - switch (mode) { + switch (getVisualMonsterMode()) { case MonsterMode::MoveNorthwards: case MonsterMode::MoveSouthwards: case MonsterMode::MoveSideways: @@ -4699,6 +4699,21 @@ bool Monster::tryLiftGargoyle() return false; } +MonsterMode Monster::getVisualMonsterMode() const +{ + if (mode != MonsterMode::Petrified) + return mode; + size_t monsterId = this->getId(); + for (auto &missile : Missiles) { + // Search the missile that will restore the original monster mode and use the saved/original monster mode from it + if (missile._mitype == MissileID::StoneCurse && missile.var2 == monsterId) { + return static_cast(missile.var1); + } + } + assert("getVisualMonsterMode: Found a monster that is infinited petrified (bug)"); + return MonsterMode::Petrified; +} + unsigned int Monster::toHitSpecial(_difficulty difficulty) const { unsigned int baseToHitSpecial = data().toHitSpecial; diff --git a/Source/monster.h b/Source/monster.h index 0b99f2a1e..a8dba5a46 100644 --- a/Source/monster.h +++ b/Source/monster.h @@ -437,6 +437,14 @@ struct Monster { // note: missing field _mAFNum } bool tryLiftGargoyle(); + + /** + * @brief Gets the visual/shown monster mode. + * + * When a monster is petrified it's monster mode is changed to MonsterMode::Petrified. + * But for graphics and rendering we show the old/real mode. + */ + [[nodiscard]] MonsterMode getVisualMonsterMode() const; }; extern size_t LevelMonsterTypeCount;