diff --git a/src/creatures/combat/combat.cpp b/src/creatures/combat/combat.cpp index e1f764e0e29..f8653117f35 100644 --- a/src/creatures/combat/combat.cpp +++ b/src/creatures/combat/combat.cpp @@ -330,111 +330,73 @@ ReturnValue Combat::canDoCombat(const std::shared_ptr &attacker, const } const auto &targetPlayer = target ? target->getPlayer() : nullptr; + const auto &attackerPlayer = attacker ? attacker->getPlayer() : nullptr; + + if (target && target->isSummon() && target->getMaster() && target->getMaster()->getPlayer() && !isInPvpZone(attacker, target)) { + return RETURNVALUE_YOUMAYNOTATTACKTHISCREATURE; + } + + if (g_game().getWorldType() == WORLD_TYPE_NO_PVP) { + if ((attackerPlayer || (attacker->getMaster() && attacker->getMaster()->getPlayer())) && targetPlayer && !isInPvpZone(attacker, target)) { + return RETURNVALUE_YOUMAYNOTATTACKTHISPLAYER; + } + } + if (target) { const std::shared_ptr &tile = target->getTile(); if (tile->hasProperty(CONST_PROP_BLOCKPROJECTILE)) { return RETURNVALUE_NOTENOUGHROOM; } + if (targetPlayer && tile->hasFlag(TILESTATE_PROTECTIONZONE)) { const auto permittedOnPz = targetPlayer->hasPermittedConditionInPZ(); return permittedOnPz ? RETURNVALUE_NOERROR : RETURNVALUE_ACTIONNOTPERMITTEDINPROTECTIONZONE; } } - if (attacker) { - const auto &attackerMaster = attacker->getMaster(); - const auto &attackerPlayer = attacker->getPlayer(); - if (targetPlayer) { - if (targetPlayer->hasFlag(PlayerFlags_t::CannotBeAttacked)) { - return RETURNVALUE_YOUMAYNOTATTACKTHISPLAYER; - } - - const auto &targetPlayerTile = targetPlayer->getTile(); - if (attackerPlayer) { - if (attackerPlayer->hasFlag(PlayerFlags_t::CannotAttackPlayer)) { - return RETURNVALUE_YOUMAYNOTATTACKTHISPLAYER; - } - - if (isProtected(attackerPlayer, targetPlayer)) { - return RETURNVALUE_YOUMAYNOTATTACKTHISPLAYER; - } + if (attacker && targetPlayer) { + if (targetPlayer->hasFlag(PlayerFlags_t::CannotBeAttacked)) { + return RETURNVALUE_YOUMAYNOTATTACKTHISPLAYER; + } - // nopvp-zone - const auto &attackerTile = attackerPlayer->getTile(); - if (targetPlayerTile && targetPlayerTile->hasFlag(TILESTATE_NOPVPZONE)) { - return RETURNVALUE_ACTIONNOTPERMITTEDINANOPVPZONE; - } else if (attackerTile && attackerTile->hasFlag(TILESTATE_NOPVPZONE) && targetPlayerTile && !targetPlayerTile->hasFlag(TILESTATE_NOPVPZONE | TILESTATE_PROTECTIONZONE)) { - return RETURNVALUE_ACTIONNOTPERMITTEDINANOPVPZONE; - } + const auto &targetPlayerTile = targetPlayer->getTile(); + const auto &attackerTile = attackerPlayer->getTile(); - if (attackerPlayer->getFaction() != FACTION_DEFAULT && attackerPlayer->getFaction() != FACTION_PLAYER && attackerPlayer->getFaction() == targetPlayer->getFaction()) { - return RETURNVALUE_YOUMAYNOTATTACKTHISPLAYER; - } - } + if (attackerPlayer->hasFlag(PlayerFlags_t::CannotAttackPlayer) || isProtected(attackerPlayer, targetPlayer)) { + return RETURNVALUE_YOUMAYNOTATTACKTHISPLAYER; + } - if (attackerMaster) { - if (const auto &masterAttackerPlayer = attackerMaster->getPlayer()) { - if (masterAttackerPlayer->hasFlag(PlayerFlags_t::CannotAttackPlayer)) { - return RETURNVALUE_YOUMAYNOTATTACKTHISPLAYER; - } + if (targetPlayerTile && targetPlayerTile->hasFlag(TILESTATE_NOPVPZONE) || (attackerTile && attackerTile->hasFlag(TILESTATE_NOPVPZONE) && !targetPlayerTile->hasFlag(TILESTATE_NOPVPZONE | TILESTATE_PROTECTIONZONE))) { + return RETURNVALUE_ACTIONNOTPERMITTEDINANOPVPZONE; + } - if (targetPlayerTile && targetPlayerTile->hasFlag(TILESTATE_NOPVPZONE)) { - return RETURNVALUE_ACTIONNOTPERMITTEDINANOPVPZONE; - } + if (attackerPlayer->getFaction() != FACTION_DEFAULT && attackerPlayer->getFaction() != FACTION_PLAYER && attackerPlayer->getFaction() == targetPlayer->getFaction()) { + return RETURNVALUE_YOUMAYNOTATTACKTHISPLAYER; + } + } - if (isProtected(masterAttackerPlayer, targetPlayer)) { - return RETURNVALUE_YOUMAYNOTATTACKTHISPLAYER; - } - } - } + if (attacker && target && target->getMonster()) { + if (attacker->getFaction() != FACTION_DEFAULT && attacker->getFaction() != FACTION_PLAYER && attacker->getMonster() && !attacker->getMonster()->isEnemyFaction(target->getFaction())) { + return RETURNVALUE_YOUMAYNOTATTACKTHISCREATURE; + } - if (attacker->getMonster() && (!attackerMaster || attackerMaster->getMonster())) { - if (attacker->getFaction() != FACTION_DEFAULT && !attacker->getMonster()->isEnemyFaction(targetPlayer->getFaction())) { - return RETURNVALUE_YOUMAYNOTATTACKTHISPLAYER; - } - } - } else if (target && target->getMonster()) { - if (attacker->getFaction() != FACTION_DEFAULT && attacker->getFaction() != FACTION_PLAYER && attacker->getMonster() && !attacker->getMonster()->isEnemyFaction(target->getFaction())) { + if (attackerPlayer) { + if (attackerPlayer->hasFlag(PlayerFlags_t::CannotAttackMonster)) { return RETURNVALUE_YOUMAYNOTATTACKTHISCREATURE; } - if (attackerPlayer) { - if (attackerPlayer->hasFlag(PlayerFlags_t::CannotAttackMonster)) { - return RETURNVALUE_YOUMAYNOTATTACKTHISCREATURE; - } - - if (target->isSummon() && target->getMaster()->getPlayer() && target->getZoneType() == ZONE_NOPVP) { - return RETURNVALUE_ACTIONNOTPERMITTEDINANOPVPZONE; - } - } else if (attacker->getMonster()) { - const auto &targetMaster = target->getMaster(); - - if ((!targetMaster || !targetMaster->getPlayer()) && attacker->getFaction() == FACTION_DEFAULT) { - if (!attackerMaster || !attackerMaster->getPlayer()) { - return RETURNVALUE_YOUMAYNOTATTACKTHISCREATURE; - } - } + if (target->isSummon() && target->getMaster()->getPlayer() && target->getZoneType() == ZONE_NOPVP) { + return RETURNVALUE_ACTIONNOTPERMITTEDINANOPVPZONE; } - } else if (target && target->getNpc()) { - return RETURNVALUE_YOUMAYNOTATTACKTHISCREATURE; - } - - if (g_game().getWorldType() == WORLD_TYPE_NO_PVP) { - if (attacker->getPlayer() || (attackerMaster && attackerMaster->getPlayer())) { - if (targetPlayer) { - if (!isInPvpZone(attacker, target)) { - return RETURNVALUE_YOUMAYNOTATTACKTHISPLAYER; - } - } - - if (target && target->isSummon() && target->getMaster()->getPlayer()) { - if (!isInPvpZone(attacker, target)) { - return RETURNVALUE_YOUMAYNOTATTACKTHISCREATURE; - } - } + } else if (attacker->getMonster()) { + if ((!target->getMaster() || !target->getMaster()->getPlayer()) && attacker->getFaction() == FACTION_DEFAULT) { + return RETURNVALUE_YOUMAYNOTATTACKTHISCREATURE; } } + } else if (target && target->getNpc()) { + return RETURNVALUE_YOUMAYNOTATTACKTHISCREATURE; } + ReturnValue ret = g_events().eventCreatureOnTargetCombat(attacker, target); if (ret == RETURNVALUE_NOERROR) { ret = g_callbacks().checkCallbackWithReturnValue(EventCallback_t::creatureOnTargetCombat, &EventCallback::creatureOnTargetCombat, attacker, target);