From fee7f4749fd2dc679c47f4fdd315b289ead9fa52 Mon Sep 17 00:00:00 2001 From: obligaron Date: Sat, 18 Jan 2025 15:46:29 +0100 Subject: [PATCH] Introduce FindGolemForPlayer and use goalVar3 to track golem <-> player relation --- Source/missiles.cpp | 29 ++++++++++++++++------------- Source/monster.cpp | 26 ++++++++++++++++++++++---- Source/monster.h | 5 +++-- Source/player.cpp | 14 +++++++------- 4 files changed, 48 insertions(+), 26 deletions(-) diff --git a/Source/missiles.cpp b/Source/missiles.cpp index 3b9155601..8f6604895 100644 --- a/Source/missiles.cpp +++ b/Source/missiles.cpp @@ -2342,22 +2342,25 @@ void AddGolem(Missile &missile, AddMissileParameter ¶meter) int playerId = missile._misource; Player &player = Players[playerId]; - Monster &golem = Monsters[playerId]; + Monster *golem = FindGolemForPlayer(player); - if (golem.position.tile != GolemHoldingCell && &player == MyPlayer) - KillMyGolem(); + // Is Golem alive? + if (golem != nullptr) { + if (&player == MyPlayer) + KillGolem(*golem); + return; + } - if (golem.position.tile == GolemHoldingCell) { - std::optional spawnPosition = FindClosestValidPosition( - [start = missile.position.start](Point target) { - return !IsTileOccupied(target) && LineClearMissile(start, target); - }, - parameter.dst, 0, 5); + std::optional spawnPosition = FindClosestValidPosition( + [start = missile.position.start](Point target) { + return !IsTileOccupied(target) && LineClearMissile(start, target); + }, + parameter.dst, 0, 5); - if (spawnPosition) { - SpawnGolem(player, golem, *spawnPosition, missile); - } - } + if (!spawnPosition) + return; + + SpawnGolem(player, *golem, *spawnPosition, missile); } void AddApocalypseBoom(Missile &missile, AddMissileParameter ¶meter) diff --git a/Source/monster.cpp b/Source/monster.cpp index e9010222d..e8812b7c6 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -1068,7 +1068,7 @@ void MonsterAttackMonster(Monster &attacker, Monster &target, int hper, int mind ApplyMonsterDamage(DamageType::Physical, target, dam); if (attacker.isPlayerMinion()) { - size_t playerId = attacker.getId(); + size_t playerId = static_cast(attacker.goalVar3); const Player &player = Players[playerId]; target.tag(player); } @@ -3833,9 +3833,8 @@ void StartMonsterDeath(Monster &monster, const Player &player, bool sendmsg) MonsterDeath(monster, md, sendmsg); } -void KillMyGolem() +void KillGolem(Monster &golem) { - Monster &golem = Monsters[MyPlayerId]; delta_kill_monster(golem, golem.position.tile, *MyPlayer); NetSendCmdLocParam1(false, CMD_MONSTDEATH, golem.position.tile, static_cast(golem.getId())); M_StartKill(golem, *MyPlayer); @@ -4001,7 +4000,7 @@ void GolumAi(Monster &golem) if (golem.pathCount > 8) golem.pathCount = 5; - if (RandomWalk(golem, Players[golem.getId()]._pdir)) + if (RandomWalk(golem, Players[golem.goalVar3]._pdir)) return; Direction md = Left(golem.direction); @@ -4516,6 +4515,24 @@ Monster *FindUniqueMonster(UniqueMonsterType monsterType) return nullptr; } +Monster *FindGolemForPlayer(const Player &player) +{ + for (size_t i = 0; i < ActiveMonsterCount; i++) { + int monsterId = ActiveMonsters[i]; + Monster &monster = Monsters[monsterId]; + if (monster.type().type != MT_GOLEM) + continue; + if (monster.position.tile == GolemHoldingCell) + continue; + if (monster.goalVar3 != player.getId()) + continue; + if (monster.hitPoints == 0) + continue; + return &monster; + } + return nullptr; +} + bool IsTileAvailable(const Monster &monster, Point position) { if (!IsTileAvailable(position)) @@ -4654,6 +4671,7 @@ void SpawnGolem(Player &player, Monster &golem, Point position, Missile &missile golem.minDamage = 2 * (missile._mispllvl + 4); golem.maxDamage = 2 * (missile._mispllvl + 8); golem.flags |= MFLAG_GOLEM; + golem.goalVar3 = player.getId(); StartSpecialStand(golem, Direction::South); UpdateEnemy(golem); if (&player == MyPlayer) { diff --git a/Source/monster.h b/Source/monster.h index 7eb567e13..018e21a5b 100644 --- a/Source/monster.h +++ b/Source/monster.h @@ -237,7 +237,7 @@ struct Monster { // note: missing field _mAFNum /** * @brief Controls monster's behaviour regarding special actions. - * Used only by @p ScavengerAi and @p MegaAi. + * Used only by @p ScavengerAi, @p MegaAi and @p GolemAi. */ int8_t goalVar3; @@ -529,7 +529,7 @@ void M_StartHit(Monster &monster, int dam); void M_StartHit(Monster &monster, const Player &player, int dam); void StartMonsterDeath(Monster &monster, const Player &player, bool sendmsg); void MonsterDeath(Monster &monster, Direction md, bool sendmsg); -void KillMyGolem(); +void KillGolem(Monster &golem); void M_StartKill(Monster &monster, const Player &player); void M_SyncStartKill(Monster &monster, Point position, const Player &player); void M_UpdateRelations(const Monster &monster); @@ -553,6 +553,7 @@ void MissToMonst(Missile &missile, Point position); Monster *FindMonsterAtPosition(Point position, bool ignoreMovingMonsters = false); Monster *FindUniqueMonster(UniqueMonsterType monsterType); +Monster *FindGolemForPlayer(const Player &player); /** * @brief Check that the given tile is available to the monster diff --git a/Source/player.cpp b/Source/player.cpp index 0b1bdc32f..ef9ba9323 100644 --- a/Source/player.cpp +++ b/Source/player.cpp @@ -2812,14 +2812,14 @@ void SyncPlrKill(Player &player, DeathReason deathReason) void RemovePlrMissiles(const Player &player) { if (leveltype != DTYPE_TOWN && &player == MyPlayer) { - Monster &golem = Monsters[MyPlayerId]; - if (golem.position.tile.x != 1 || golem.position.tile.y != 0) { - KillMyGolem(); - AddCorpse(golem.position.tile, golem.type().corpseId, golem.direction); - int mx = golem.position.tile.x; - int my = golem.position.tile.y; + Monster *golem = FindGolemForPlayer(player); + if (golem != nullptr) { + KillGolem(*golem); + AddCorpse(golem->position.tile, golem->type().corpseId, golem->direction); + int mx = golem->position.tile.x; + int my = golem->position.tile.y; dMonster[mx][my] = 0; - golem.isInvalid = true; + golem->isInvalid = true; DeleteMonsterList(); } }