From 4598cf12ba92a89f8f79535a6aad762416bce312 Mon Sep 17 00:00:00 2001 From: ramon-bernardo Date: Wed, 23 Oct 2024 21:15:03 -0300 Subject: [PATCH 1/5] New methods to handle creatures with a master --- src/combat.cpp | 78 ++++----------- src/combat.h | 1 - src/creature.cpp | 10 +- src/creature.h | 57 ++++++++++- src/game.cpp | 3 +- src/luascript.cpp | 224 +++++++++++++++++++++++++++++++++++++++++-- src/luascript.h | 16 ++++ src/monster.cpp | 57 ++++------- src/player.cpp | 42 +++----- src/player.h | 1 - src/protocolgame.cpp | 10 +- src/tile.cpp | 38 ++++---- 12 files changed, 371 insertions(+), 166 deletions(-) diff --git a/src/combat.cpp b/src/combat.cpp index 0f8e326270..ce60f4a29c 100644 --- a/src/combat.cpp +++ b/src/combat.cpp @@ -164,19 +164,6 @@ ConditionType_t Combat::DamageToConditionType(CombatType_t type) } } -bool Combat::isPlayerCombat(const Creature* target) -{ - if (target->getPlayer()) { - return true; - } - - if (target->isSummon() && target->getMaster()->getPlayer()) { - return true; - } - - return false; -} - ReturnValue Combat::canTargetCreature(Player* attacker, Creature* target) { if (attacker == target) { @@ -194,7 +181,7 @@ ReturnValue Combat::canTargetCreature(Player* attacker, Creature* target) } // nopvp-zone - if (isPlayerCombat(target)) { + if (target->hasPlayerOwned()) { if (attacker->getZone() == ZONE_NOPVP) { return RETURNVALUE_ACTIONNOTPERMITTEDINANOPVPZONE; } @@ -317,19 +304,17 @@ ReturnValue Combat::canDoCombat(Creature* attacker, Creature* target) } } - if (attacker->isSummon()) { - if (const Player* masterAttackerPlayer = attacker->getMaster()->getPlayer()) { - if (masterAttackerPlayer->hasFlag(PlayerFlag_CannotAttackPlayer)) { - return RETURNVALUE_YOUMAYNOTATTACKTHISPLAYER; - } + if (const Player* masterAttackerPlayer = attacker->getPlayerMaster()) { + if (masterAttackerPlayer->hasFlag(PlayerFlag_CannotAttackPlayer)) { + return RETURNVALUE_YOUMAYNOTATTACKTHISPLAYER; + } - if (targetPlayer->getTile()->hasFlag(TILESTATE_NOPVPZONE)) { - return RETURNVALUE_ACTIONNOTPERMITTEDINANOPVPZONE; - } + if (targetPlayer->getTile()->hasFlag(TILESTATE_NOPVPZONE)) { + return RETURNVALUE_ACTIONNOTPERMITTEDINANOPVPZONE; + } - if (isProtected(masterAttackerPlayer, targetPlayer)) { - return RETURNVALUE_YOUMAYNOTATTACKTHISPLAYER; - } + if (isProtected(masterAttackerPlayer, targetPlayer)) { + return RETURNVALUE_YOUMAYNOTATTACKTHISPLAYER; } } } else if (target->getMonster()) { @@ -338,34 +323,21 @@ ReturnValue Combat::canDoCombat(Creature* attacker, Creature* target) return RETURNVALUE_YOUMAYNOTATTACKTHISCREATURE; } - if (target->isSummon() && target->getMaster()->getPlayer() && target->getZone() == ZONE_NOPVP) { + if (target->isPlayerSummon() && target->getZone() == ZONE_NOPVP) { return RETURNVALUE_ACTIONNOTPERMITTEDINANOPVPZONE; } } else if (attacker->getMonster()) { - const Creature* targetMaster = target->getMaster(); - - if (!targetMaster || !targetMaster->getPlayer()) { - const Creature* attackerMaster = attacker->getMaster(); - - if (!attackerMaster || !attackerMaster->getPlayer()) { - return RETURNVALUE_YOUMAYNOTATTACKTHISCREATURE; - } + if (!target->isPlayerSummon() && !attacker->isPlayerSummon()) { + return RETURNVALUE_YOUMAYNOTATTACKTHISCREATURE; } } } if (g_game.getWorldType() == WORLD_TYPE_NO_PVP) { - if (attacker->getPlayer() || (attacker->isSummon() && attacker->getMaster()->getPlayer())) { - if (target->getPlayer()) { - if (!isInPvpZone(attacker, target)) { - return RETURNVALUE_YOUMAYNOTATTACKTHISPLAYER; - } - } - - if (target->isSummon() && target->getMaster()->getPlayer()) { - if (!isInPvpZone(attacker, target)) { - return RETURNVALUE_YOUMAYNOTATTACKTHISCREATURE; - } + if (attacker->hasPlayerOwned() && target->hasPlayerOwned()) { + if (!isInPvpZone(attacker, target)) { + return target->getPlayer() ? RETURNVALUE_YOUMAYNOTATTACKTHISPLAYER + : RETURNVALUE_YOUMAYNOTATTACKTHISCREATURE; } } } @@ -560,14 +532,7 @@ void Combat::combatTileEffects(const SpectatorVec& spectators, Creature* caster, } if (caster) { - Player* casterPlayer; - if (caster->isSummon()) { - casterPlayer = caster->getMaster()->getPlayer(); - } else { - casterPlayer = caster->getPlayer(); - } - - if (casterPlayer) { + if (Player* casterPlayer = caster->getPlayerOwned()) { if (g_game.getWorldType() == WORLD_TYPE_NO_PVP || tile->hasFlag(TILESTATE_NOPVPZONE)) { if (itemId == ITEM_FIREFIELD_PVP_FULL) { itemId = ITEM_FIREFIELD_NOPVP; @@ -1403,11 +1368,8 @@ void MagicField::onStepInField(Creature* creature) bool harmfulField = true; if (g_game.getWorldType() == WORLD_TYPE_NO_PVP || getTile()->hasFlag(TILESTATE_NOPVPZONE)) { - Creature* owner = g_game.getCreatureByID(ownerId); - if (owner) { - if (owner->getPlayer() || (owner->isSummon() && owner->getMaster()->getPlayer())) { - harmfulField = false; - } + if (Creature* owner = g_game.getCreatureByID(ownerId); owner->hasPlayerOwned()) { + harmfulField = false; } } diff --git a/src/combat.h b/src/combat.h index 5bc110e659..cb7f617c14 100644 --- a/src/combat.h +++ b/src/combat.h @@ -90,7 +90,6 @@ class Combat static bool isInPvpZone(const Creature* attacker, const Creature* target); static bool isProtected(const Player* attacker, const Player* target); - static bool isPlayerCombat(const Creature* target); static CombatType_t ConditionToDamageType(ConditionType_t type); static ConditionType_t DamageToConditionType(CombatType_t type); static ReturnValue canTargetCreature(Player* attacker, Creature* target); diff --git a/src/creature.cpp b/src/creature.cpp index 84471c26f0..372bbb8d29 100644 --- a/src/creature.cpp +++ b/src/creature.cpp @@ -963,7 +963,7 @@ void Creature::goToFollowCreature() getPathSearchParams(followCreature, fpp); Monster* monster = getMonster(); - if (monster && !monster->getMaster() && (monster->isFleeing() || fpp.maxTargetDist > 1)) { + if (monster && !monster->isSummon() && (monster->isFleeing() || fpp.maxTargetDist > 1)) { Direction dir = DIRECTION_NONE; if (monster->isFleeing()) { @@ -1463,11 +1463,11 @@ int64_t Creature::getStepDuration() const double duration = std::floor(1000 * groundSpeed / calculatedStepSpeed); int64_t stepDuration = std::ceil(duration / 50) * 50; - const Monster* monster = getMonster(); - if (monster && monster->isTargetNearby() && !monster->isFleeing() && !monster->getMaster()) { - stepDuration *= 2; + if (const Monster* monster = getMonster(); monster->isTargetNearby()) { + if (!monster->isFleeing()) { + stepDuration *= 2; + } } - return stepDuration; } diff --git a/src/creature.h b/src/creature.h index 361afa0ac7..132600b0b8 100644 --- a/src/creature.h +++ b/src/creature.h @@ -202,8 +202,15 @@ class Creature : virtual public Thing bool checkDefense = false, bool checkArmor = false, bool field = false, bool ignoreResistances = false); + /// Returns the master of this creature. + Creature* getMaster() const { return master; } + /// Checks if the creature is a summon, i.e., if it has a master. + bool isSummon() const { return master != nullptr; } + + /// Sets a new master for this creature. bool setMaster(Creature* newMaster); + /// Removes the current master from this creature. void removeMaster() { if (master) { @@ -212,9 +219,55 @@ class Creature : virtual public Thing } } - bool isSummon() const { return master != nullptr; } - Creature* getMaster() const { return master; } + /// Checks if the creature is owned by a player, either directly or through its master. + bool hasPlayerOwned() const { return getPlayer() || (master && master->getPlayer()); } + /// Returns the player that owns this creature, either directly or through its master. + Player* getPlayerOwned() { return getPlayer() ? getPlayer() : (master ? master->getPlayer() : nullptr); } + /// Returns the player that owns this creature, either directly or through its master. + const Player* getPlayerOwned() const + { + return getPlayer() ? getPlayer() : (master ? master->getPlayer() : nullptr); + } + + /// Checks if the creature is owned by an NPC, either directly or through its master. + bool hasNpcOwned() const { return getNpc() || (master && master->getNpc()); } + /// Returns the NPC that owns this creature, either directly or through its master. + Npc* getNpcOwned() { return getNpc() ? getNpc() : (master ? master->getNpc() : nullptr); } + /// Returns the NPC that owns this creature, either directly or through its master. + const Npc* getNpcOwned() const { return getNpc() ? getNpc() : (master ? master->getNpc() : nullptr); } + + /// Checks if the creature is owned by a monster, either directly or through its master. + bool hasMonsterOwned() const { return getMonster() || (master && master->getMonster()); } + /// Returns the monster that owns this creature, either directly or through its master. + Monster* getMonsterOwned() { return getMonster() ? getMonster() : (master ? master->getMonster() : nullptr); } + /// Returns the monster that owns this creature, either directly or through its master. + const Monster* getMonsterOwned() const + { + return getMonster() ? getMonster() : (master ? master->getMonster() : nullptr); + } + /// Checks if the creature's master is a player. + bool isPlayerSummon() const { return master && master->getPlayer(); } + /// Returns the player who is the master of this creature. + Player* getPlayerMaster() { return master ? master->getPlayer() : nullptr; } + /// Returns the player who is the master of this creature. + const Player* getPlayerMaster() const { return master ? master->getPlayer() : nullptr; } + + /// Checks if the creature's master is an NPC. + bool isNpcSummon() const { return master && master->getNpc(); } + /// Returns the NPC who is the master of this creature. + Npc* getNpcMaster() { return master ? master->getNpc() : nullptr; } + /// Returns the NPC who is the master of this creature. + const Npc* getNpcMaster() const { return master ? master->getNpc() : nullptr; } + + /// Checks if the creature's master is a monster. + bool isMonsterSummon() const { return master && master->getMonster(); } + /// Returns the monster who is the master of this creature. + Monster* getMonsterMaster() { return master ? master->getMonster() : nullptr; } + /// Returns the monster who is the master of this creature. + const Monster* getMonsterMaster() const { return master ? master->getMonster() : nullptr; } + + /// Retrieves the list of summoned creatures. const std::list& getSummons() const { return summons; } virtual int32_t getArmor() const { return 0; } diff --git a/src/game.cpp b/src/game.cpp index 710f1df7bb..0dd423858f 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -571,8 +571,7 @@ bool Game::removeCreature(Creature* creature, bool isLogout /* = true*/) spectator->onRemoveCreature(creature, isLogout); } - Creature* master = creature->getMaster(); - if (master && !master->isRemoved()) { + if (Creature* master = creature->getMaster(); !master->isRemoved()) { creature->setMaster(nullptr); } diff --git a/src/luascript.cpp b/src/luascript.cpp index 24b0d43d69..62ab850855 100644 --- a/src/luascript.cpp +++ b/src/luascript.cpp @@ -2682,8 +2682,24 @@ void LuaScriptInterface::registerFunctions() registerMethod(L, "Creature", "getFollowCreature", LuaScriptInterface::luaCreatureGetFollowCreature); registerMethod(L, "Creature", "setFollowCreature", LuaScriptInterface::luaCreatureSetFollowCreature); + registerMethod(L, "Creature", "isSummon", LuaScriptInterface::luaCreatureIsSummon); registerMethod(L, "Creature", "getMaster", LuaScriptInterface::luaCreatureGetMaster); registerMethod(L, "Creature", "setMaster", LuaScriptInterface::luaCreatureSetMaster); + registerMethod(L, "Creature", "removeMaster", LuaScriptInterface::luaCreatureRemoveMaster); + + registerMethod(L, "Creature", "hasPlayerOwned", LuaScriptInterface::luaCreatureHasPlayerOwned); + registerMethod(L, "Creature", "getPlayerOwned", LuaScriptInterface::luaCreatureGetPlayerOwned); + registerMethod(L, "Creature", "hasNpcOwned", LuaScriptInterface::luaCreatureHasNpcOwned); + registerMethod(L, "Creature", "getNpcOwned", LuaScriptInterface::luaCreatureGetNpcOwned); + registerMethod(L, "Creature", "hasMonsterOwned", LuaScriptInterface::luaCreatureHasMonsterOwned); + registerMethod(L, "Creature", "getMonsterOwned", LuaScriptInterface::luaCreatureGetMonsterOwned); + + registerMethod(L, "Creature", "isPlayerSummon", LuaScriptInterface::luaCreatureIsPlayerSummon); + registerMethod(L, "Creature", "getPlayerMaster", LuaScriptInterface::luaCreatureGetPlayerMaster); + registerMethod(L, "Creature", "isNpcSummon", LuaScriptInterface::luaCreatureIsNpcSummon); + registerMethod(L, "Creature", "getNpcMaster", LuaScriptInterface::luaCreatureGetNpcMaster); + registerMethod(L, "Creature", "isMonsterSummon", LuaScriptInterface::luaCreatureIsMonsterSummon); + registerMethod(L, "Creature", "getMonsterMaster", LuaScriptInterface::luaCreatureGetMonsterMaster); registerMethod(L, "Creature", "getLight", LuaScriptInterface::luaCreatureGetLight); registerMethod(L, "Creature", "setLight", LuaScriptInterface::luaCreatureSetLight); @@ -8125,6 +8141,18 @@ int LuaScriptInterface::luaCreatureSetFollowCreature(lua_State* L) return 1; } +int LuaScriptInterface::luaCreatureIsSummon(lua_State* L) +{ + // creature:isSummon() + Creature* creature = tfs::lua::getUserdata(L, 1); + if (creature) { + tfs::lua::pushBoolean(L, creature->isSummon()); + } else { + lua_pushnil(L); + } + return 1; +} + int LuaScriptInterface::luaCreatureGetMaster(lua_State* L) { // creature:getMaster() @@ -8134,14 +8162,12 @@ int LuaScriptInterface::luaCreatureGetMaster(lua_State* L) return 1; } - Creature* master = creature->getMaster(); - if (!master) { + if (Creature* master = creature->getMaster()) { + tfs::lua::pushUserdata(L, master); + tfs::lua::setCreatureMetatable(L, -1, master); + } else { lua_pushnil(L); - return 1; } - - tfs::lua::pushUserdata(L, master); - tfs::lua::setCreatureMetatable(L, -1, master); return 1; } @@ -8161,6 +8187,192 @@ int LuaScriptInterface::luaCreatureSetMaster(lua_State* L) return 1; } +int LuaScriptInterface::luaCreatureRemoveMaster(lua_State* L) +{ + // creature:removeMaster() + if (Creature* creature = tfs::lua::getUserdata(L, 1)) { + creature->removeMaster(); + tfs::lua::pushBoolean(L, true); + } else { + lua_pushnil(L); + } + return 1; +} + +int LuaScriptInterface::luaCreatureHasPlayerOwned(lua_State* L) +{ + // creature:hasPlayerOwned() + if (Creature* creature = tfs::lua::getUserdata(L, 1)) { + tfs::lua::pushBoolean(L, creature->hasPlayerOwned()); + } else { + lua_pushnil(L); + } + return 1; +} + +int LuaScriptInterface::luaCreatureGetPlayerOwned(lua_State* L) +{ + // creature:getPlayerOwned() + Creature* creature = tfs::lua::getUserdata(L, 1); + if (!creature) { + lua_pushnil(L); + return 1; + } + + if (Player* player = creature->getPlayerOwned()) { + tfs::lua::pushUserdata(L, player); + tfs::lua::setMetatable(L, -1, "Player"); + } else { + lua_pushnil(L); + } + return 1; +} + +int LuaScriptInterface::luaCreatureHasNpcOwned(lua_State* L) +{ + // creature:hasNpcOwned() + if (Creature* creature = tfs::lua::getUserdata(L, 1)) { + tfs::lua::pushBoolean(L, creature->hasNpcOwned()); + } else { + lua_pushnil(L); + } + return 1; +} + +int LuaScriptInterface::luaCreatureGetNpcOwned(lua_State* L) +{ + // creature:getNpcOwned() + Creature* creature = tfs::lua::getUserdata(L, 1); + if (!creature) { + lua_pushnil(L); + return 1; + } + + if (Npc* npc = creature->getNpcOwned()) { + tfs::lua::pushUserdata(L, npc); + tfs::lua::setMetatable(L, -1, "Npc"); + } else { + lua_pushnil(L); + } + return 1; +} + +int LuaScriptInterface::luaCreatureHasMonsterOwned(lua_State* L) +{ + // creature:hasMonsterOwned() + if (Creature* creature = tfs::lua::getUserdata(L, 1)) { + tfs::lua::pushBoolean(L, creature->hasMonsterOwned()); + } else { + lua_pushnil(L); + } + return 1; +} + +int LuaScriptInterface::luaCreatureGetMonsterOwned(lua_State* L) +{ + // creature:getMonsterOwned() + Creature* creature = tfs::lua::getUserdata(L, 1); + if (!creature) { + lua_pushnil(L); + return 1; + } + + if (Monster* monster = creature->getMonsterOwned()) { + tfs::lua::pushUserdata(L, monster); + tfs::lua::setMetatable(L, -1, "Monster"); + } else { + lua_pushnil(L); + } + return 1; +} + +int LuaScriptInterface::luaCreatureIsPlayerSummon(lua_State* L) +{ + // creature:isPlayerSummon() + if (Creature* creature = tfs::lua::getUserdata(L, 1)) { + tfs::lua::pushBoolean(L, creature->isPlayerSummon()); + } else { + lua_pushnil(L); + } + return 1; +} + +int LuaScriptInterface::luaCreatureGetPlayerMaster(lua_State* L) +{ + // creature:getPlayerMaster() + Creature* creature = tfs::lua::getUserdata(L, 1); + if (!creature) { + lua_pushnil(L); + return 1; + } + + if (Player* player = creature->getPlayerMaster()) { + tfs::lua::pushUserdata(L, player); + tfs::lua::setMetatable(L, -1, "Player"); + } else { + lua_pushnil(L); + } + return 1; +} + +int LuaScriptInterface::luaCreatureIsNpcSummon(lua_State* L) +{ + // creature:isNpcSummon() + if (Creature* creature = tfs::lua::getUserdata(L, 1)) { + tfs::lua::pushBoolean(L, creature->isNpcSummon()); + } else { + lua_pushnil(L); + } + return 1; +} + +int LuaScriptInterface::luaCreatureGetNpcMaster(lua_State* L) +{ + // creature:getNpcMaster() + Creature* creature = tfs::lua::getUserdata(L, 1); + if (!creature) { + lua_pushnil(L); + return 1; + } + + if (Npc* npc = creature->getNpcMaster()) { + tfs::lua::pushUserdata(L, npc); + tfs::lua::setMetatable(L, -1, "Npc"); + } else { + lua_pushnil(L); + } + return 1; +} + +int LuaScriptInterface::luaCreatureIsMonsterSummon(lua_State* L) +{ + // creature:isMonsterSummon() + if (Creature* creature = tfs::lua::getUserdata(L, 1)) { + tfs::lua::pushBoolean(L, creature->isMonsterSummon()); + } else { + lua_pushnil(L); + } + return 1; +} + +int LuaScriptInterface::luaCreatureGetMonsterMaster(lua_State* L) +{ + // creature:getMonsterMaster() + Creature* creature = tfs::lua::getUserdata(L, 1); + if (!creature) { + lua_pushnil(L); + return 1; + } + + if (Monster* monster = creature->getMonsterMaster()) { + tfs::lua::pushUserdata(L, monster); + tfs::lua::setMetatable(L, -1, "Monster"); + } else { + lua_pushnil(L); + } + return 1; +} + int LuaScriptInterface::luaCreatureGetLight(lua_State* L) { // creature:getLight() diff --git a/src/luascript.h b/src/luascript.h index 6a7a00e388..e150314988 100644 --- a/src/luascript.h +++ b/src/luascript.h @@ -552,8 +552,24 @@ class LuaScriptInterface static int luaCreatureGetFollowCreature(lua_State* L); static int luaCreatureSetFollowCreature(lua_State* L); + static int luaCreatureIsSummon(lua_State* L); static int luaCreatureGetMaster(lua_State* L); static int luaCreatureSetMaster(lua_State* L); + static int luaCreatureRemoveMaster(lua_State* L); + + static int luaCreatureHasPlayerOwned(lua_State* L); + static int luaCreatureGetPlayerOwned(lua_State* L); + static int luaCreatureHasNpcOwned(lua_State* L); + static int luaCreatureGetNpcOwned(lua_State* L); + static int luaCreatureHasMonsterOwned(lua_State* L); + static int luaCreatureGetMonsterOwned(lua_State* L); + + static int luaCreatureIsPlayerSummon(lua_State* L); + static int luaCreatureGetPlayerMaster(lua_State* L); + static int luaCreatureIsNpcSummon(lua_State* L); + static int luaCreatureGetNpcMaster(lua_State* L); + static int luaCreatureIsMonsterSummon(lua_State* L); + static int luaCreatureGetMonsterMaster(lua_State* L); static int luaCreatureGetLight(lua_State* L); static int luaCreatureSetLight(lua_State* L); diff --git a/src/monster.cpp b/src/monster.cpp index 19a4239752..f66e78e085 100644 --- a/src/monster.cpp +++ b/src/monster.cpp @@ -428,43 +428,31 @@ void Monster::onCreatureEnter(Creature* creature) bool Monster::isFriend(const Creature* creature) const { - if (isSummon() && getMaster()->getPlayer()) { - const Player* masterPlayer = getMaster()->getPlayer(); - const Player* tmpPlayer = nullptr; - - if (creature->getPlayer()) { - tmpPlayer = creature->getPlayer(); - } else { - const Creature* creatureMaster = creature->getMaster(); - - if (creatureMaster && creatureMaster->getPlayer()) { - tmpPlayer = creatureMaster->getPlayer(); + if (const Player* masterPlayer = getPlayerMaster()) { + if (const Player* ownedPlayer = creature->getPlayerOwned()) { + if (masterPlayer == ownedPlayer || masterPlayer->isPartner(ownedPlayer)) { + return true; } } - - if (tmpPlayer && (tmpPlayer == getMaster() || masterPlayer->isPartner(tmpPlayer))) { - return true; - } } else if (creature->getMonster() && !creature->isSummon()) { return true; } - return false; } bool Monster::isOpponent(const Creature* creature) const { - if (isSummon() && getMaster()->getPlayer()) { - if (creature != getMaster()) { - return true; - } - } else { - if ((creature->getPlayer() && !creature->getPlayer()->hasFlag(PlayerFlag_IgnoredByMonsters)) || - (creature->getMaster() && creature->getMaster()->getPlayer())) { - return true; - } + if (const Player* player = getPlayerMaster(); creature != player) { + return true; + } + + if (const Player* player = creature->getPlayer(); !player->hasFlag(PlayerFlag_IgnoredByMonsters)) { + return true; } + if (creature->isPlayerSummon()) { + return true; + } return false; } @@ -1170,7 +1158,7 @@ bool Monster::getNextStep(Direction& direction, uint32_t& flags) result = getRandomStep(getPosition(), direction); } } else if ((isSummon() && isMasterInRange) || followCreature || walkingToSpawn) { - if (!hasFollowPath && getMaster() && !getMaster()->getPlayer()) { + if (!hasFollowPath && isSummon() && !isPlayerSummon()) { randomStepping = true; result = getRandomStep(getPosition(), direction); } else { @@ -1848,16 +1836,13 @@ void Monster::death(Creature*) Item* Monster::getCorpse(Creature* lastHitCreature, Creature* mostDamageCreature) { Item* corpse = Creature::getCorpse(lastHitCreature, mostDamageCreature); - if (corpse) { - if (mostDamageCreature) { - if (mostDamageCreature->getPlayer()) { - corpse->setCorpseOwner(mostDamageCreature->getID()); - } else { - const Creature* mostDamageCreatureMaster = mostDamageCreature->getMaster(); - if (mostDamageCreatureMaster && mostDamageCreatureMaster->getPlayer()) { - corpse->setCorpseOwner(mostDamageCreatureMaster->getID()); - } - } + if (!corpse) { + return nullptr; + } + + if (mostDamageCreature) { + if (const Player* mostDamagePlayer = mostDamageCreature->getPlayerOwned()) { + corpse->setCorpseOwner(mostDamagePlayer->getID()); } } return corpse; diff --git a/src/player.cpp b/src/player.cpp index 755678dff5..bbaf395810 100644 --- a/src/player.cpp +++ b/src/player.cpp @@ -2054,9 +2054,7 @@ void Player::death(Creature* lastHitCreature) if (skillLoss) { uint8_t unfairFightReduction = 100; - bool lastHitPlayer = Player::lastHitIsPlayer(lastHitCreature); - - if (lastHitPlayer) { + if (lastHitCreature && lastHitCreature->hasPlayerOwned()) { uint32_t sumLevels = 0; uint32_t inFightTicks = getNumber(ConfigManager::PZ_LOCKED); for (const auto& it : damageMap) { @@ -2130,7 +2128,7 @@ void Player::death(Creature* lastHitCreature) } if (blessings.test(5)) { - if (lastHitPlayer) { + if (lastHitCreature && lastHitCreature->hasPlayerOwned()) { blessings.reset(5); } else { blessings.reset(); @@ -2194,12 +2192,11 @@ void Player::death(Creature* lastHitCreature) bool Player::dropCorpse(Creature* lastHitCreature, Creature* mostDamageCreature, bool lastHitUnjustified, bool mostDamageUnjustified) { - if (getZone() != ZONE_PVP || !Player::lastHitIsPlayer(lastHitCreature)) { - return Creature::dropCorpse(lastHitCreature, mostDamageCreature, lastHitUnjustified, mostDamageUnjustified); + if (getZone() == ZONE_PVP && lastHitCreature && lastHitCreature->hasPlayerOwned()) { + setDropLoot(true); + return false; } - - setDropLoot(true); - return false; + return Creature::dropCorpse(lastHitCreature, mostDamageCreature, lastHitUnjustified, mostDamageUnjustified); } Item* Player::getCorpse(Creature* lastHitCreature, Creature* mostDamageCreature) @@ -3691,10 +3688,9 @@ void Player::onAttackedCreatureDrainHealth(Creature* target, int32_t points) { Creature::onAttackedCreatureDrainHealth(target, points); - if (target) { - if (party && !Combat::isPlayerCombat(target)) { - Monster* tmpMonster = target->getMonster(); - if (tmpMonster && tmpMonster->isHostile()) { + if (party && target) { + if (!target->hasPlayerOwned()) { + if (const Monster* monster = target->getMonster(); monster->isHostile()) { // We have fulfilled a requirement for shared experience party->updatePlayerTicks(this, points); } @@ -3709,10 +3705,8 @@ void Player::onTargetCreatureGainHealth(Creature* target, int32_t points) if (target->getPlayer()) { tmpPlayer = target->getPlayer(); - } else if (Creature* targetMaster = target->getMaster()) { - if (Player* targetMasterPlayer = targetMaster->getPlayer()) { - tmpPlayer = targetMasterPlayer; - } + } else if (Player* targetMasterPlayer = target->getPlayerMaster()) { + tmpPlayer = targetMasterPlayer; } if (isPartner(tmpPlayer)) { @@ -3805,20 +3799,6 @@ bool Player::isImmune(ConditionType_t type) const bool Player::isAttackable() const { return !hasFlag(PlayerFlag_CannotBeAttacked); } -bool Player::lastHitIsPlayer(Creature* lastHitCreature) -{ - if (!lastHitCreature) { - return false; - } - - if (lastHitCreature->getPlayer()) { - return true; - } - - Creature* lastHitMaster = lastHitCreature->getMaster(); - return lastHitMaster && lastHitMaster->getPlayer(); -} - void Player::changeHealth(int32_t healthChange, bool sendHealthChange /* = true*/) { Creature::changeHealth(healthChange, sendHealthChange); diff --git a/src/player.h b/src/player.h index be1c3a508c..2fccc8def7 100644 --- a/src/player.h +++ b/src/player.h @@ -433,7 +433,6 @@ class Player final : public Creature, public Cylinder bool isImmune(ConditionType_t type) const override; bool hasShield() const; bool isAttackable() const override; - static bool lastHitIsPlayer(Creature* lastHitCreature); void changeHealth(int32_t healthChange, bool sendHealthChange = true) override; void changeMana(int32_t manaChange); diff --git a/src/protocolgame.cpp b/src/protocolgame.cpp index 5edfbb3dcb..d84b64b886 100644 --- a/src/protocolgame.cpp +++ b/src/protocolgame.cpp @@ -3425,13 +3425,9 @@ void ProtocolGame::AddCreature(NetworkMessage& msg, const Creature* creature, bo uint32_t masterId = 0; if (creatureType == CREATURETYPE_MONSTER) { - const Creature* master = creature->getMaster(); - if (master) { - masterPlayer = master->getPlayer(); - if (masterPlayer) { - masterId = master->getID(); - creatureType = CREATURETYPE_SUMMON_OWN; - } + if (const Player* masterPlayer = creature->getPlayerMaster()) { + masterId = masterPlayer->getID(); + creatureType = CREATURETYPE_SUMMON_OWN; } } diff --git a/src/tile.cpp b/src/tile.cpp index dd41a7ed40..9cb182a605 100644 --- a/src/tile.cpp +++ b/src/tile.cpp @@ -501,25 +501,29 @@ ReturnValue Tile::queryAdd(int32_t, const Thing& thing, uint32_t, uint32_t flags return RETURNVALUE_NOTPOSSIBLE; } - const CreatureVector* creatures = getCreatures(); - if (monster->canPushCreatures() && !monster->isSummon()) { - if (creatures) { - for (Creature* tileCreature : *creatures) { - if (tileCreature->getPlayer() && tileCreature->getPlayer()->isInGhostMode()) { - continue; - } + if (const CreatureVector* creatures = getCreatures()) { + if (!creatures->empty()) { + if (monster->canPushCreatures() && !monster->isSummon()) { + for (Creature* tileCreature : *creatures) { + if (const Player* tilePlayer = tileCreature->getPlayer(); tilePlayer->isInGhostMode()) { + continue; + } + + if (!tileCreature->isPushable()) { + return RETURNVALUE_NOTPOSSIBLE; + } - const Monster* creatureMonster = tileCreature->getMonster(); - if (!creatureMonster || !tileCreature->isPushable() || - (creatureMonster->isSummon() && creatureMonster->getMaster()->getPlayer())) { - return RETURNVALUE_NOTPOSSIBLE; + const Monster* creatureMonster = tileCreature->getMonster(); + if (!creatureMonster || creatureMonster->isPlayerSummon()) { + return RETURNVALUE_NOTPOSSIBLE; + } + } + } else { + for (const Creature* tileCreature : *creatures) { + if (!tileCreature->isInGhostMode()) { + return RETURNVALUE_NOTENOUGHROOM; + } } - } - } - } else if (creatures && !creatures->empty()) { - for (const Creature* tileCreature : *creatures) { - if (!tileCreature->isInGhostMode()) { - return RETURNVALUE_NOTENOUGHROOM; } } } From 857c727fae8f6130180ffb90678b3901e1fd7563 Mon Sep 17 00:00:00 2001 From: ramon-bernardo Date: Wed, 23 Oct 2024 21:39:23 -0300 Subject: [PATCH 2/5] Replace lua codebase with new methods --- data/creaturescripts/scripts/drop_loot.lua | 14 +------------- data/creaturescripts/scripts/player_death.lua | 11 +++-------- data/lib/compat/compat.lua | 4 ++-- data/scripts/actions/others/music_box.lua | 2 +- data/scripts/actions/others/nail_case.lua | 2 +- data/scripts/actions/others/taming.lua | 2 +- .../creaturescripts/monster/white_deer_death.lua | 2 +- .../creaturescripts/monster/white_deer_scouts.lua | 2 +- .../creaturescripts/player/bestiary_kills.lua | 2 +- data/scripts/spells/healing/mass_healing.lua | 3 +-- .../scripts/spells/monster/frozen_minion_beam.lua | 5 ++--- .../scripts/spells/monster/frozen_minion_heal.lua | 9 ++++----- .../scripts/spells/monster/frozen_minion_wave.lua | 5 ++--- data/scripts/spells/monster/heal_monsters.lua | 15 ++++----------- data/scripts/spells/monster/heal_monsters_9x9.lua | 15 ++++----------- data/scripts/spells/monster/icicle_heal.lua | 7 +++---- 16 files changed, 32 insertions(+), 68 deletions(-) diff --git a/data/creaturescripts/scripts/drop_loot.lua b/data/creaturescripts/scripts/drop_loot.lua index bfd96805d9..6534eace3e 100644 --- a/data/creaturescripts/scripts/drop_loot.lua +++ b/data/creaturescripts/scripts/drop_loot.lua @@ -6,19 +6,7 @@ function onDeath(player, corpse, killer, mostDamageKiller, lastHitUnjustified, m local amulet = player:getSlotItem(CONST_SLOT_NECKLACE) local isRedOrBlack = table.contains({SKULL_RED, SKULL_BLACK}, player:getSkull()) if amulet and amulet.itemid == ITEM_AMULETOFLOSS and not isRedOrBlack then - local isPlayer = false - if killer then - if killer:isPlayer() then - isPlayer = true - else - local master = killer:getMaster() - if master and master:isPlayer() then - isPlayer = true - end - end - end - - if not isPlayer or not player:hasBlessing(6) then + if not killer or not killer:hasPlayerOwned() or not player:hasBlessing(6) then player:removeItem(ITEM_AMULETOFLOSS, 1, -1, false) end else diff --git a/data/creaturescripts/scripts/player_death.lua b/data/creaturescripts/scripts/player_death.lua index 7537290f80..5cb3168669 100644 --- a/data/creaturescripts/scripts/player_death.lua +++ b/data/creaturescripts/scripts/player_death.lua @@ -6,15 +6,10 @@ local function getKiller(killer) return false, "field item" end - if killer:isPlayer() then - return true, killer:getName() + local player = killer:getPlayerOwned() + if player and player ~= killer then + return true, player:getName() end - - local master = killer:getMaster() - if master and master ~= killer and master:isPlayer() then - return true, master:getName() - end - return false, killer:getName() end diff --git a/data/lib/compat/compat.lua b/data/lib/compat/compat.lua index f612c1ab13..4566a02523 100644 --- a/data/lib/compat/compat.lua +++ b/data/lib/compat/compat.lua @@ -894,7 +894,7 @@ function doSetMonsterTarget(cid, target) return false end - if monster:getMaster() then + if monster:isSummon() then return true end @@ -913,7 +913,7 @@ function doMonsterChangeTarget(cid) return false end - if monster:getMaster() then + if monster:isSummon() then return true end diff --git a/data/scripts/actions/others/music_box.lua b/data/scripts/actions/others/music_box.lua index 0fd958d78d..93780520a1 100644 --- a/data/scripts/actions/others/music_box.lua +++ b/data/scripts/actions/others/music_box.lua @@ -58,7 +58,7 @@ local config = { local musicBox = Action() function musicBox.onUse(player, item, fromPosition, target, toPosition, isHotkey) - if not target:isCreature() or not target:isMonster() or target:getMaster() then + if not target:isCreature() or not target:isMonster() or target:isSummon() then return false end diff --git a/data/scripts/actions/others/nail_case.lua b/data/scripts/actions/others/nail_case.lua index 23546712e9..79627876b2 100644 --- a/data/scripts/actions/others/nail_case.lua +++ b/data/scripts/actions/others/nail_case.lua @@ -8,7 +8,7 @@ local messages = { local nailCase = Action() function nailCase.onUse(player, item, fromPosition, target, toPosition, isHotkey) - if not target:isCreature() or not target:isMonster() or target:getMaster() then + if not target:isCreature() or not target:isMonster() or target:isSummon() then return false end diff --git a/data/scripts/actions/others/taming.lua b/data/scripts/actions/others/taming.lua index 8341f3bda7..2b86863f97 100644 --- a/data/scripts/actions/others/taming.lua +++ b/data/scripts/actions/others/taming.lua @@ -418,7 +418,7 @@ function taming.onUse(player, item, fromPosition, target, toPosition, isHotkey) end if target.type == TYPE_MONSTER then - if target:getMaster() then + if target:isSummon() then return false end end diff --git a/data/scripts/creaturescripts/monster/white_deer_death.lua b/data/scripts/creaturescripts/monster/white_deer_death.lua index d3cca2bc99..7ba8699ddf 100644 --- a/data/scripts/creaturescripts/monster/white_deer_death.lua +++ b/data/scripts/creaturescripts/monster/white_deer_death.lua @@ -7,7 +7,7 @@ local creatureevent = CreatureEvent("WhiteDeerDeath") function creatureevent.onDeath(creature, corpse, killer, mostDamageKiller, lastHitUnjustified, mostDamageUnjustified) local targetMonster = creature:getMonster() - if not targetMonster or targetMonster:getMaster() then + if not targetMonster or targetMonster:isSummon() then return true end diff --git a/data/scripts/creaturescripts/monster/white_deer_scouts.lua b/data/scripts/creaturescripts/monster/white_deer_scouts.lua index 5a688a55b1..6ea76c59a4 100644 --- a/data/scripts/creaturescripts/monster/white_deer_scouts.lua +++ b/data/scripts/creaturescripts/monster/white_deer_scouts.lua @@ -2,7 +2,7 @@ local creatureevent = CreatureEvent("WhiteDeerScouts") function creatureevent.onDeath(creature, corpse, killer, mostDamageKiller, lastHitUnjustified, mostDamageUnjustified) local targetMonster = creature:getMonster() - if not targetMonster or targetMonster:getMaster() then + if not targetMonster or targetMonster:isSummon() then return true end diff --git a/data/scripts/creaturescripts/player/bestiary_kills.lua b/data/scripts/creaturescripts/player/bestiary_kills.lua index 4819aee4aa..6a5f3708bd 100644 --- a/data/scripts/creaturescripts/player/bestiary_kills.lua +++ b/data/scripts/creaturescripts/player/bestiary_kills.lua @@ -25,7 +25,7 @@ local creatureEvent = CreatureEvent("BestiaryKills") function creatureEvent.onKill(player, target) local monster = target:getMonster() - if not monster or monster:getMaster() then + if not monster or monster:isSummon() then return true end diff --git a/data/scripts/spells/healing/mass_healing.lua b/data/scripts/spells/healing/mass_healing.lua index 91100b1fe5..847f2c3087 100644 --- a/data/scripts/spells/healing/mass_healing.lua +++ b/data/scripts/spells/healing/mass_healing.lua @@ -10,8 +10,7 @@ function spell.onCastSpell(creature, variant) local min = (creature:getLevel() / 5) + (creature:getMagicLevel() * 4.6) + 100 local max = (creature:getLevel() / 5) + (creature:getMagicLevel() * 9.6) + 125 for _, target in ipairs(combat:getTargets(creature, variant)) do - local master = target:getMaster() - if target:isPlayer() or master and master:isPlayer() then + if target:hasPlayerOwned() then doTargetCombat(creature, target, COMBAT_HEALING, min, max) end end diff --git a/data/scripts/spells/monster/frozen_minion_beam.lua b/data/scripts/spells/monster/frozen_minion_beam.lua index 21609d4e4f..bb871410eb 100644 --- a/data/scripts/spells/monster/frozen_minion_beam.lua +++ b/data/scripts/spells/monster/frozen_minion_beam.lua @@ -6,12 +6,11 @@ combat:setArea(createCombatArea(AREA_BEAM7)) function onTargetCreature(creature, target) local min = 200 local max = 700 - local master = target:getMaster() - if target:isPlayer() and not master or master and master:isPlayer() then + if target:hasPlayerOwned() then doTargetCombat(0, target, COMBAT_ICEDAMAGE, min, max, CONST_ME_NONE) return true end - + doTargetCombat(0, target, COMBAT_HEALING, min, max, CONST_ME_NONE) return true end diff --git a/data/scripts/spells/monster/frozen_minion_heal.lua b/data/scripts/spells/monster/frozen_minion_heal.lua index ec9049a7ac..f45d5ff653 100644 --- a/data/scripts/spells/monster/frozen_minion_heal.lua +++ b/data/scripts/spells/monster/frozen_minion_heal.lua @@ -4,13 +4,12 @@ combat:setParameter(COMBAT_PARAM_AGGRESSIVE, 0) combat:setArea(createCombatArea(AREA_CIRCLE2X2)) function onTargetCreature(creature, target) - local min = 100 - local max = 200 - local master = target:getMaster() - if target:isPlayer() and not master or master and master:isPlayer() then + if target:hasPlayerOwned() then return true end - + + local min = 100 + local max = 200 doTargetCombat(0, target, COMBAT_HEALING, min, max, CONST_ME_NONE) return true end diff --git a/data/scripts/spells/monster/frozen_minion_wave.lua b/data/scripts/spells/monster/frozen_minion_wave.lua index ea01f80045..ff53ee79b3 100644 --- a/data/scripts/spells/monster/frozen_minion_wave.lua +++ b/data/scripts/spells/monster/frozen_minion_wave.lua @@ -14,12 +14,11 @@ combat:setArea(createCombatArea(area)) function onTargetCreature(creature, target) local min = 200 local max = 700 - local master = target:getMaster() - if target:isPlayer() and not master or master and master:isPlayer() then + if target:hasPlayerOwned() then doTargetCombat(0, target, COMBAT_ICEDAMAGE, min, max, CONST_ME_NONE) return true end - + doTargetCombat(0, target, COMBAT_HEALING, min, max, CONST_ME_NONE) return true end diff --git a/data/scripts/spells/monster/heal_monsters.lua b/data/scripts/spells/monster/heal_monsters.lua index fc022eecb2..45e4f9dd4b 100644 --- a/data/scripts/spells/monster/heal_monsters.lua +++ b/data/scripts/spells/monster/heal_monsters.lua @@ -1,17 +1,10 @@ function onTargetCreature(creature, target) - local player = creature:getPlayer() - local min = 100 - local max = 300 - local master = target:getMaster() - - if target:isPlayer() then + if target:hasPlayerOwned() then return true end - - if master then - return true - end - + + local min = 100 + local max = 300 doTargetCombatHealth(0, target, COMBAT_HEALING, min, max, CONST_ME_NONE) return true end diff --git a/data/scripts/spells/monster/heal_monsters_9x9.lua b/data/scripts/spells/monster/heal_monsters_9x9.lua index 514fe31c4a..ef9241ce4d 100644 --- a/data/scripts/spells/monster/heal_monsters_9x9.lua +++ b/data/scripts/spells/monster/heal_monsters_9x9.lua @@ -1,17 +1,10 @@ function onTargetCreature(creature, target) - local player = creature:getPlayer() - local min = 0 - local max = 1000 - local master = target:getMaster() - - if target:isPlayer() then + if target:hasPlayerOwned() then return true end - - if master then - return true - end - + + local min = 0 + local max = 1000 doTargetCombatHealth(0, target, COMBAT_HEALING, min, max, CONST_ME_NONE) return true end diff --git a/data/scripts/spells/monster/icicle_heal.lua b/data/scripts/spells/monster/icicle_heal.lua index 61cfe979a7..53eba2dad4 100644 --- a/data/scripts/spells/monster/icicle_heal.lua +++ b/data/scripts/spells/monster/icicle_heal.lua @@ -4,13 +4,12 @@ combat:setParameter(COMBAT_PARAM_AGGRESSIVE, 0) combat:setArea(createCombatArea(AREA_CIRCLE3X3)) function onTargetCreature(creature, target) - local min = 400 - local max = 600 - local master = target:getMaster() - if target:isPlayer() and not master or master and master:isPlayer() then + if target:hasPlayerOwned() then return true end + local min = 400 + local max = 600 doTargetCombat(0, target, COMBAT_HEALING, min, max, CONST_ME_NONE) return true end From 96f931d00645ad14d6c818ddd808964f2d575bbb Mon Sep 17 00:00:00 2001 From: ramon-bernardo Date: Wed, 23 Oct 2024 21:43:05 -0300 Subject: [PATCH 3/5] Remove whitespace lua --- data/scripts/spells/monster/frozen_minion_beam.lua | 2 +- data/scripts/spells/monster/frozen_minion_wave.lua | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/data/scripts/spells/monster/frozen_minion_beam.lua b/data/scripts/spells/monster/frozen_minion_beam.lua index bb871410eb..0abf95c9e9 100644 --- a/data/scripts/spells/monster/frozen_minion_beam.lua +++ b/data/scripts/spells/monster/frozen_minion_beam.lua @@ -10,7 +10,7 @@ function onTargetCreature(creature, target) doTargetCombat(0, target, COMBAT_ICEDAMAGE, min, max, CONST_ME_NONE) return true end - + doTargetCombat(0, target, COMBAT_HEALING, min, max, CONST_ME_NONE) return true end diff --git a/data/scripts/spells/monster/frozen_minion_wave.lua b/data/scripts/spells/monster/frozen_minion_wave.lua index ff53ee79b3..e09de912df 100644 --- a/data/scripts/spells/monster/frozen_minion_wave.lua +++ b/data/scripts/spells/monster/frozen_minion_wave.lua @@ -18,7 +18,7 @@ function onTargetCreature(creature, target) doTargetCombat(0, target, COMBAT_ICEDAMAGE, min, max, CONST_ME_NONE) return true end - + doTargetCombat(0, target, COMBAT_HEALING, min, max, CONST_ME_NONE) return true end From 88f1b7a6cfbaf9f4695e4cedd8fcba4776b4b1be Mon Sep 17 00:00:00 2001 From: ramon-bernardo Date: Wed, 23 Oct 2024 22:25:14 -0300 Subject: [PATCH 4/5] Remove unused variable 'masterPlayer' --- src/protocolgame.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/protocolgame.cpp b/src/protocolgame.cpp index d84b64b886..1b0ee1bccb 100644 --- a/src/protocolgame.cpp +++ b/src/protocolgame.cpp @@ -3421,7 +3421,6 @@ void ProtocolGame::AddCreature(NetworkMessage& msg, const Creature* creature, bo { CreatureType_t creatureType = creature->getType(); const Player* otherPlayer = creature->getPlayer(); - const Player* masterPlayer = nullptr; uint32_t masterId = 0; if (creatureType == CREATURETYPE_MONSTER) { From 29d7f709515c0210abfc5a45e002be99e6381ad6 Mon Sep 17 00:00:00 2001 From: ramon-bernardo Date: Thu, 24 Oct 2024 19:14:43 -0300 Subject: [PATCH 5/5] Fix nullptr check --- src/combat.cpp | 6 ++++-- src/creature.cpp | 4 ++-- src/monster.cpp | 6 ++++-- src/player.cpp | 8 +++++--- src/tile.cpp | 6 ++++-- 5 files changed, 19 insertions(+), 11 deletions(-) diff --git a/src/combat.cpp b/src/combat.cpp index ce60f4a29c..1bef87bb4f 100644 --- a/src/combat.cpp +++ b/src/combat.cpp @@ -1368,8 +1368,10 @@ void MagicField::onStepInField(Creature* creature) bool harmfulField = true; if (g_game.getWorldType() == WORLD_TYPE_NO_PVP || getTile()->hasFlag(TILESTATE_NOPVPZONE)) { - if (Creature* owner = g_game.getCreatureByID(ownerId); owner->hasPlayerOwned()) { - harmfulField = false; + if (Creature* owner = g_game.getCreatureByID(ownerId)) { + if (owner->hasPlayerOwned()) { + harmfulField = false; + } } } diff --git a/src/creature.cpp b/src/creature.cpp index 372bbb8d29..b7e76a2979 100644 --- a/src/creature.cpp +++ b/src/creature.cpp @@ -1463,8 +1463,8 @@ int64_t Creature::getStepDuration() const double duration = std::floor(1000 * groundSpeed / calculatedStepSpeed); int64_t stepDuration = std::ceil(duration / 50) * 50; - if (const Monster* monster = getMonster(); monster->isTargetNearby()) { - if (!monster->isFleeing()) { + if (const Monster* monster = getMonster()) { + if (monster->isTargetNearby() && !monster->isFleeing()) { stepDuration *= 2; } } diff --git a/src/monster.cpp b/src/monster.cpp index f66e78e085..52e417199d 100644 --- a/src/monster.cpp +++ b/src/monster.cpp @@ -446,8 +446,10 @@ bool Monster::isOpponent(const Creature* creature) const return true; } - if (const Player* player = creature->getPlayer(); !player->hasFlag(PlayerFlag_IgnoredByMonsters)) { - return true; + if (const Player* player = creature->getPlayer()) { + if (!player->hasFlag(PlayerFlag_IgnoredByMonsters)) { + return true; + } } if (creature->isPlayerSummon()) { diff --git a/src/player.cpp b/src/player.cpp index bbaf395810..b5e1d0f7c4 100644 --- a/src/player.cpp +++ b/src/player.cpp @@ -3690,9 +3690,11 @@ void Player::onAttackedCreatureDrainHealth(Creature* target, int32_t points) if (party && target) { if (!target->hasPlayerOwned()) { - if (const Monster* monster = target->getMonster(); monster->isHostile()) { - // We have fulfilled a requirement for shared experience - party->updatePlayerTicks(this, points); + if (const Monster* monster = target->getMonster()) { + if (monster->isHostile()) { + // We have fulfilled a requirement for shared experience + party->updatePlayerTicks(this, points); + } } } } diff --git a/src/tile.cpp b/src/tile.cpp index 9cb182a605..a1e5245e4b 100644 --- a/src/tile.cpp +++ b/src/tile.cpp @@ -505,8 +505,10 @@ ReturnValue Tile::queryAdd(int32_t, const Thing& thing, uint32_t, uint32_t flags if (!creatures->empty()) { if (monster->canPushCreatures() && !monster->isSummon()) { for (Creature* tileCreature : *creatures) { - if (const Player* tilePlayer = tileCreature->getPlayer(); tilePlayer->isInGhostMode()) { - continue; + if (const Player* tilePlayer = tileCreature->getPlayer()) { + if (tilePlayer->isInGhostMode()) { + continue; + } } if (!tileCreature->isPushable()) {