Browse Source

Add getLeader helper for monsters in a pack

pull/4977/head
ephphatha 4 years ago committed by Anders Jenbo
parent
commit
1e0f2c149c
  1. 6
      Source/loadsave.cpp
  2. 40
      Source/monster.cpp
  3. 4
      Source/monster.h
  4. 2
      Source/qol/monhealthbar.cpp

6
Source/loadsave.cpp

@ -659,6 +659,8 @@ void LoadMonster(LoadHelper *file, Monster &monster)
if (monster.talkMsg == TEXT_KING1) // Fix original bad mapping of NONE for monsters
monster.talkMsg = TEXT_NONE;
monster.leader = file->NextLE<uint8_t>();
if (monster.leader == 0)
monster.leader = Monster::NoLeader; // Golems shouldn't be leaders of other monsters
monster.leaderRelation = static_cast<LeaderRelation>(file->NextLE<uint8_t>());
monster.packSize = file->NextLE<uint8_t>();
monster.lightId = file->NextLE<int8_t>();
@ -1400,8 +1402,8 @@ void SaveMonster(SaveHelper *file, Monster &monster)
file->WriteLE<uint16_t>(monster.magicResistance);
file->Skip(2); // Alignment
file->WriteLE<int32_t>(monster.talkMsg == TEXT_NONE ? 0 : monster.talkMsg); // Replicate original bad mapping of none for monsters
file->WriteLE<uint8_t>(monster.leader);
file->WriteLE<int32_t>(monster.talkMsg == TEXT_NONE ? 0 : monster.talkMsg); // Replicate original bad mapping of none for monsters
file->WriteLE<uint8_t>(monster.leader == Monster::NoLeader ? 0 : monster.leader); // Vanilla uses 0 as the default leader which corresponds to player 0s golem
file->WriteLE<uint8_t>(static_cast<std::uint8_t>(monster.leaderRelation));
file->WriteLE<uint8_t>(monster.packSize);
// vanilla compatibility

40
Source/monster.cpp

@ -241,7 +241,7 @@ void InitMonster(Monster &monster, Direction rd, int mtype, Point position)
monster.maxDamage2 = monster.data().mMaxDamage2;
monster.armorClass = monster.data().mArmorClass;
monster.magicResistance = monster.data().mMagicRes;
monster.leader = 0;
monster.leader = Monster::NoLeader;
monster.leaderRelation = LeaderRelation::None;
monster.flags = monster.data().mFlags;
monster.talkMsg = TEXT_NONE;
@ -1754,18 +1754,18 @@ bool IsLineNotSolid(Point startPoint, Point endPoint)
void FollowTheLeader(Monster &monster)
{
if (monster.leader == 0)
if (monster.leaderRelation != LeaderRelation::Leashed)
return;
if (monster.leaderRelation != LeaderRelation::Leashed)
Monster *leader = monster.getLeader();
if (leader == nullptr)
return;
auto &leader = Monsters[monster.leader];
if (monster.activeForTicks >= leader.activeForTicks)
if (monster.activeForTicks >= leader->activeForTicks)
return;
monster.position.last = leader.position.tile;
monster.activeForTicks = leader.activeForTicks - 1;
monster.position.last = leader->position.tile;
monster.activeForTicks = leader->activeForTicks - 1;
}
void GroupUnity(Monster &monster)
@ -1773,12 +1773,12 @@ void GroupUnity(Monster &monster)
if (monster.leaderRelation == LeaderRelation::None)
return;
// Someone with a leaderRelation should have a leader ...
assert(monster.leader >= 0);
// And no unique monster would be a minion of someone else!
// No unique monster would be a minion of someone else!
assert(monster.uniqType == 0);
auto &leader = Monsters[monster.leader];
// Someone with a leaderRelation should have a leader, if we end up trying to access a nullptr then the relation was already broken...
auto &leader = *monster.getLeader();
if (IsLineNotSolid(monster.position.tile, leader.position.future)) {
if (monster.leaderRelation == LeaderRelation::Separated
&& monster.position.tile.WalkingDistance(leader.position.future) < 4) {
@ -2345,7 +2345,7 @@ void ScavengerAi(int monsterId)
if (monster.hitPoints < (monster.maxHitPoints / 2) && monster.goal != MonsterGoal::Healing) {
if (monster.leaderRelation != LeaderRelation::None) {
if (monster.leaderRelation == LeaderRelation::Leashed)
Monsters[monster.leader].packSize--;
monster.getLeader()->packSize--;
monster.leaderRelation = LeaderRelation::None;
}
monster.goal = MonsterGoal::Healing;
@ -4007,12 +4007,12 @@ void M_UpdateLeader(int monsterId)
for (size_t j = 0; j < ActiveMonsterCount; j++) {
auto &minion = Monsters[ActiveMonsters[j]];
if (minion.leaderRelation == LeaderRelation::Leashed && minion.leader == monsterId)
if (minion.leaderRelation == LeaderRelation::Leashed && minion.getLeader() == &monster)
minion.leaderRelation = LeaderRelation::None;
}
if (monster.leaderRelation == LeaderRelation::Leashed) {
Monsters[monster.leader].packSize--;
monster.getLeader()->packSize--;
}
}
@ -4296,7 +4296,7 @@ bool DirOK(int monsterId, Direction mdir)
if (!IsRelativeMoveOK(monster, position, mdir))
return false;
if (monster.leaderRelation == LeaderRelation::Leashed) {
return futurePosition.WalkingDistance(Monsters[monster.leader].position.future) < 4;
return futurePosition.WalkingDistance(monster.getLeader()->position.future) < 4;
}
if (monster.uniqType == 0 || UniqueMonstersData[monster.uniqType - 1].monsterPack != UniqueMonsterPack::Leashed)
return true;
@ -4310,7 +4310,7 @@ bool DirOK(int monsterId, Direction mdir)
continue;
auto &minion = Monsters[mi - 1];
if (minion.leaderRelation == LeaderRelation::Leashed && minion.leader == monsterId) {
if (minion.leaderRelation == LeaderRelation::Leashed && minion.getLeader() == &monster) {
mcount++;
}
}
@ -4845,6 +4845,14 @@ void decode_enemy(Monster &monster, int enemyId)
return std::distance<const Monster *>(&Monsters[0], this);
}
Monster *Monster::getLeader() const
{
if (leader == Monster::NoLeader)
return nullptr;
return &Monsters[leader];
}
void Monster::checkStandAnimationIsLoaded(Direction mdir)
{
if (IsAnyOf(mode, MonsterMode::Stand, MonsterMode::Talk)) {

4
Source/monster.h

@ -239,6 +239,8 @@ struct Monster { // note: missing field _mAFNum
uint8_t packSize;
int8_t lightId;
static constexpr uint8_t NoLeader = -1;
/**
* @brief Sets the current cell sprite to match the desired desiredDirection and animation sequence
* @param graphic Animation sequence of interest
@ -289,6 +291,8 @@ struct Monster { // note: missing field _mAFNum
*/
[[nodiscard]] size_t getId() const;
[[nodiscard]] Monster *getLeader() const;
/**
* @brief Is the monster currently walking?
*/

2
Source/qol/monhealthbar.cpp

@ -136,7 +136,7 @@ void DrawMonsterHealthBar(const Surface &out)
DrawString(out, monster.name, { position + Displacement { -1, 1 }, { width, height } }, style | UiFlags::ColorBlack);
if (monster.uniqType != 0)
style |= UiFlags::ColorWhitegold;
else if (monster.leader != 0)
else if (monster.leader != Monster::NoLeader)
style |= UiFlags::ColorBlue;
else
style |= UiFlags::ColorWhite;

Loading…
Cancel
Save