Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Conditionally prevent damaging and spell auto-targeting Golem #7010

Open
wants to merge 16 commits into
base: master
Choose a base branch
from
33 changes: 27 additions & 6 deletions Source/missiles.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ bool MonsterMHit(const Player &player, int monsterId, int mindam, int maxdam, in
{
auto &monster = Monsters[monsterId];

if (!monster.isPossibleToHit() || monster.isImmune(t, damageType))
if (!monster.isPossibleToHit() || monster.isImmune(t, damageType) || !monster.canPlayerDamage(player))
return false;

int hit = RandomIntLessThan(100);
Expand Down Expand Up @@ -3528,13 +3528,24 @@ void ProcessChainLightning(Missile &missile)
Point position = missile.position.tile;
Point dst { missile.var1, missile.var2 };
Direction dir = GetDirection(position, dst);

AddMissile(position, dst, dir, MissileID::LightningControl, TARGET_MONSTERS, id, 1, missile._mispllvl);

int rad = std::min<int>(missile._mispllvl + 3, MaxCrawlRadius);

Crawl(1, rad, [&](Displacement displacement) {
Point target = position + displacement;
if (InDungeonBounds(target) && dMonster[target.x][target.y] > 0) {
dir = GetDirection(position, target);
AddMissile(position, target, dir, MissileID::LightningControl, TARGET_MONSTERS, id, 1, missile._mispllvl);
const auto &monsterId = dMonster[target.x][target.y];

if (InDungeonBounds(target) && monsterId > 0) {
const auto &player = Players[id];
const auto &monster = Monsters[std::abs(monsterId - 1)];

// Should we also be checking isPossibleToHit() and isImmune()?
if (monster.canPlayerDamage(player)) {
dir = GetDirection(position, target);
AddMissile(position, target, dir, MissileID::LightningControl, TARGET_MONSTERS, id, 1, missile._mispllvl);
}
}
return false;
});
Expand Down Expand Up @@ -4029,13 +4040,19 @@ void ProcessElemental(Missile &missile)
if (missile.var3 == 1) {
missile.var3 = 2;
missile._mirange = 255;

auto *player = missile.sourcePlayer();
auto *nextMonster = FindClosest(missilePosition, 19);
if (nextMonster != nullptr) {

// Should we also be checking isPossibleToHit() and isImmune()?
if (nextMonster != nullptr && nextMonster->canPlayerDamage(*player)) {
Direction sd = GetDirection(missilePosition, nextMonster->position.tile);

SetMissDir(missile, sd);
UpdateMissileVelocity(missile, nextMonster->position.tile, 16);
} else {
Direction sd = Players[missile._misource]._pdir;

SetMissDir(missile, sd);
UpdateMissileVelocity(missile, missilePosition + sd, 16);
}
Expand Down Expand Up @@ -4074,13 +4091,17 @@ void ProcessBoneSpirit(Missile &missile)
if (missile.var3 == 1) {
missile.var3 = 2;
missile._mirange = 255;
auto *player = missile.sourcePlayer();
auto *monster = FindClosest(c, 19);
if (monster != nullptr) {

// Should we also be checking isPossibleToHit() and isImmune()?
if (monster != nullptr && monster->canPlayerDamage(*player)) {
missile._midam = monster->hitPoints >> 7;
SetMissDir(missile, GetDirection(c, monster->position.tile));
UpdateMissileVelocity(missile, monster->position.tile, 16);
} else {
Direction sd = Players[missile._misource]._pdir;

SetMissDir(missile, sd);
UpdateMissileVelocity(missile, c + sd, 16);
}
Expand Down
6 changes: 6 additions & 0 deletions Source/monster.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4829,6 +4829,12 @@ bool Monster::isPlayerMinion() const
return (flags & MFLAG_GOLEM) != 0 && (flags & MFLAG_BERSERK) == 0;
}

bool Monster::canPlayerDamage(const Player &player) const
{
return !(player.getId() == getId()
|| (isPlayerMinion() && sgGameInitInfo.bFriendlyFire == 0 && player.friendlyMode));
}

bool Monster::isPossibleToHit() const
{
return !(hitPoints >> 6 <= 0
Expand Down
4 changes: 4 additions & 0 deletions Source/monster.h
Original file line number Diff line number Diff line change
Expand Up @@ -437,6 +437,10 @@ struct Monster { // note: missing field _mAFNum
* Is this a player's golem?
*/
[[nodiscard]] bool isPlayerMinion() const;
/**
* Can the player damage this monster?
*/
[[nodiscard]] bool canPlayerDamage(const Player &player) const;

bool isPossibleToHit() const;
void tag(const Player &tagger);
Expand Down
2 changes: 1 addition & 1 deletion Source/player.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -571,7 +571,7 @@ bool PlrHitMonst(Player &player, Monster &monster, bool adjacentDamage = false)
{
int hper = 0;

if (!monster.isPossibleToHit())
if (!monster.isPossibleToHit() || !monster.canPlayerDamage(player))
return false;

if (adjacentDamage) {
Expand Down
4 changes: 4 additions & 0 deletions Source/spells.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,10 @@ int GetManaAmount(const Player &player, SpellID sn)

void ConsumeSpell(Player &player, SpellID sn)
{
Monster &golem = Monsters[player.getId()];
kphoenix137 marked this conversation as resolved.
Show resolved Hide resolved

if (golem.hitPoints <= 0 && &player == MyPlayer)
kphoenix137 marked this conversation as resolved.
Show resolved Hide resolved
return;
switch (player.executedSpell.spellType) {
case SpellType::Skill:
case SpellType::Invalid:
Expand Down
Loading