bool Game::combatChangeMana(Creature* attacker, Creature* target, int32_t manaChange, CombatOrigin origin)
{
if (manaChange > 0) {
if (attacker) {
const Player* attackerPlayer = attacker->getPlayer();
if (attackerPlayer && attackerPlayer->getSkull() == SKULL_BLACK && target->getPlayer() && attackerPlayer->getSkullClient(target) == SKULL_NONE) {
return false;
}
}
if (origin != ORIGIN_NONE) {
const auto& events = target->getCreatureEvents(CREATURE_EVENT_MANACHANGE);
if (!events.empty()) {
for (CreatureEvent* creatureEvent : events) {
creatureEvent->executeManaChange(target, attacker, manaChange, origin);
}
return combatChangeMana(attacker, target, manaChange, ORIGIN_NONE);
}
}
target->changeMana(manaChange);
} else {
const Position& targetPos = target->getPosition();
if (!target->isAttackable()) {
if (!target->isInGhostMode()) {
addMagicEffect(targetPos, CONST_ME_POFF);
}
return false;
}
Player* attackerPlayer;
if (attacker) {
attackerPlayer = attacker->getPlayer();
} else {
attackerPlayer = nullptr;
}
Player* targetPlayer = target->getPlayer();
if (attackerPlayer && targetPlayer && attackerPlayer->getSkull() == SKULL_BLACK && attackerPlayer->getSkullClient(targetPlayer) == SKULL_NONE) {
return false;
}
int32_t manaLoss = std::min<int32_t>(target->getMana(), -manaChange);
BlockType_t blockType = target->blockHit(attacker, COMBAT_MANADRAIN, manaLoss);
if (blockType != BLOCK_NONE) {
addMagicEffect(targetPos, CONST_ME_POFF);
return false;
}
if (manaLoss <= 0) {
return true;
}
if (origin != ORIGIN_NONE) {
const auto& events = target->getCreatureEvents(CREATURE_EVENT_MANACHANGE);
if (!events.empty()) {
for (CreatureEvent* creatureEvent : events) {
creatureEvent->executeManaChange(target, attacker, manaChange, origin);
}
return combatChangeMana(attacker, target, manaChange, ORIGIN_NONE);
}
}
target->drainMana(attacker, manaLoss);
std::string damageString = std::to_string(manaLoss);
std::string spectatorMessage = ucfirst(target->getNameDescription()) + " loses " + damageString + " mana";
if (attacker) {
spectatorMessage += " due to ";
if (attacker == target) {
spectatorMessage += (targetPlayer ? (targetPlayer->getSex() == PLAYERSEX_FEMALE ? "her own attack" : "his own attack") : "its own attack");
} else {
spectatorMessage += "an attack by " + attacker->getNameDescription();
}
}
spectatorMessage += '.';
TextMessage message;
message.position = targetPos;
message.primary.value = manaLoss;
message.primary.color = TEXTCOLOR_BLUE;
SpectatorVec list;
map.getSpectators(list, targetPos, false, true);
for (Creature* spectator : list) {
Player* tmpPlayer = spectator->getPlayer();
if (tmpPlayer == attackerPlayer && attackerPlayer != targetPlayer) {
message.type = MESSAGE_DAMAGE_DEALT;
message.text = ucfirst(target->getNameDescription()) + " loses " + damageString + " mana due to your attack.";
} else if (tmpPlayer == targetPlayer) {
message.type = MESSAGE_DAMAGE_RECEIVED;
if (!attacker) {
message.text = "You lose " + damageString + " mana.";
} else if (targetPlayer == attackerPlayer) {
message.text = "You lose " + damageString + " mana due to your own attack.";
} else {
message.text = "You lose " + damageString + " mana due to an attack by " + attacker->getNameDescription() + '.';
}
} else {
message.type = MESSAGE_DAMAGE_OTHERS;
message.text = spectatorMessage;
}
tmpPlayer->sendTextMessage(message);
}
}
return true;
}