Could someone help me with this problem. I inserted the exeta amp res spell in the source, without errors in the engine, but the monsters are not having the effect of the spell
Post automatically merged:
C++:
void Combat::doCombat(Creature* caster, Creature* target) const
{
//target combat callback function
if (params.combatType != COMBAT_NONE) {
CombatDamage damage = getCombatDamage(caster, target);
bool canCombat = !params.aggressive || (caster != target && Combat::canDoCombat(caster, target) == RETURNVALUE_NOERROR);
if ((caster == target || canCombat) && params.impactEffect != CONST_ME_NONE) {
g_game.addMagicEffect(target->getPosition(), params.impactEffect);
}
if (canCombat) {
doTargetCombat(caster, target, damage, params);
}
} else {
if (!params.aggressive || (caster != target && Combat::canDoCombat(caster, target) == RETURNVALUE_NOERROR)) {
SpectatorVec spectators;
g_game.map.getSpectators(spectators, target->getPosition(), true, true);
if (params.origin != ORIGIN_MELEE) {
for (const auto& condition : params.conditionList) {
if (caster == target || !target->isImmune(condition->getType())) {
Condition* conditionCopy = condition->clone();
conditionCopy->setParam(CONDITION_PARAM_OWNER, caster->getID());
target->addCombatCondition(conditionCopy);
}
}
}
if (params.dispelType == CONDITION_PARALYZE) {
target->removeCondition(CONDITION_PARALYZE);
} else {
target->removeCombatCondition(params.dispelType);
}
combatTileEffects(spectators, caster, target->getTile(), params);
if (params.targetCallback) {
params.targetCallback->onTargetCombat(caster, target);
}
/*
if (params.impactEffect != CONST_ME_NONE) {
g_game.addMagicEffect(target->getPosition(), params.impactEffect);
}
*/
if (caster && params.distanceEffect != CONST_ANI_NONE) {
addDistanceEffect(caster, caster->getPosition(), target->getPosition(), params.distanceEffect);
}
}
}
}
void Combat::doCombat(Creature* caster, const Position& position) const
{
//area combat callback function
if (params.combatType != COMBAT_NONE) {
CombatDamage damage = getCombatDamage(caster, nullptr);
doAreaCombat(caster, position, area.get(), damage, params);
} else {
auto tiles = caster ? getCombatArea(caster->getPosition(), position, area.get()) : getCombatArea(position, position, area.get());
SpectatorVec spectators;
uint32_t maxX = 0;
uint32_t maxY = 0;
//calculate the max viewable range
for (Tile* tile : tiles) {
const Position& tilePos = tile->getPosition();
uint32_t diff = Position::getDistanceX(tilePos, position);
if (diff > maxX) {
maxX = diff;
}
diff = Position::getDistanceY(tilePos, position);
if (diff > maxY) {
maxY = diff;
}
}
const int32_t rangeX = maxX + Map::maxViewportX;
const int32_t rangeY = maxY + Map::maxViewportY;
g_game.map.getSpectators(spectators, position, true, true, rangeX, rangeX, rangeY, rangeY);
postCombatEffects(caster, position, params);
for (Tile* tile : tiles) {
if (canDoCombat(caster, tile, params.aggressive) != RETURNVALUE_NOERROR) {
continue;
}
combatTileEffects(spectators, caster, tile, params);
if (CreatureVector* creatures = tile->getCreatures()) {
const Creature* topCreature = tile->getTopCreature();
for (Creature* creature : *creatures) {
if (params.targetCasterOrTopMost) {
if (caster && caster->getTile() == tile) {
if (creature != caster) {
continue;
}
} else if (creature != topCreature) {
continue;
}
}
if (!params.aggressive || (caster != creature && Combat::canDoCombat(caster, creature) == RETURNVALUE_NOERROR)) {
for (const auto& condition : params.conditionList) {
if (caster == creature || !creature->isImmune(condition->getType())) {
Condition* conditionCopy = condition->clone();
if (caster) {
conditionCopy->setParam(CONDITION_PARAM_OWNER, caster->getID());
}
//TODO: infight condition until all aggressive conditions has ended
creature->addCombatCondition(conditionCopy);
}
}
}
if (params.dispelType == CONDITION_PARALYZE) {
creature->removeCondition(CONDITION_PARALYZE);
} else {
creature->removeCombatCondition(params.dispelType);
}
if (params.targetCallback) {
params.targetCallback->onTargetCombat(caster, creature);
}
if (params.targetCasterOrTopMost) {
break;
}
}
}
}
}
}
void Combat::doTargetCombat(Creature* caster, Creature* target, CombatDamage& damage, const CombatParams& params)
{
if (caster && target && params.distanceEffect != CONST_ANI_NONE) {
addDistanceEffect(caster, caster->getPosition(), target->getPosition(), params.distanceEffect);
}
Player* casterPlayer = caster ? caster->getPlayer() : nullptr;
bool success = false;
if (damage.primary.type != COMBAT_MANADRAIN) {
if (g_game.combatBlockHit(damage, caster, target, params.blockedByShield, params.blockedByArmor, params.itemId != 0, params.ignoreResistances)) {
return;
}
if (casterPlayer) {
Player* targetPlayer = target ? target->getPlayer() : nullptr;
if (targetPlayer && casterPlayer != targetPlayer && targetPlayer->getSkull() != SKULL_BLACK && damage.primary.type != COMBAT_HEALING) {
damage.primary.value /= 2;
damage.secondary.value /= 2;
}
if (!damage.critical && damage.primary.type != COMBAT_HEALING && damage.origin != ORIGIN_CONDITION) {
uint16_t chance = casterPlayer->getSpecialSkill(SPECIALSKILL_CRITICALHITCHANCE);
uint16_t skill = casterPlayer->getSpecialSkill(SPECIALSKILL_CRITICALHITAMOUNT);
if (chance > 0 && skill > 0 && normal_random(1, 100) <= chance) {
damage.primary.value += std::round(damage.primary.value * (skill / 100.));
damage.secondary.value += std::round(damage.secondary.value * (skill / 100.));
damage.critical = true;
}
}
}
success = g_game.combatChangeHealth(caster, target, damage);
} else {
success = g_game.combatChangeMana(caster, target, damage);
}
if (success) {
if (damage.blockType == BLOCK_NONE || damage.blockType == BLOCK_ARMOR) {
for (const auto& condition : params.conditionList) {
if (caster == target || !target->isImmune(condition->getType())) {
Condition* conditionCopy = condition->clone();
if (caster) {
conditionCopy->setParam(CONDITION_PARAM_OWNER, caster->getID());
}
//TODO: infight condition until all aggressive conditions has ended
target->addCombatCondition(conditionCopy);
}
}
}
if (damage.critical) {
g_game.addMagicEffect(target->getPosition(), CONST_ME_BLOODYSTEPS);
}
if (!damage.leeched && damage.primary.type != COMBAT_HEALING && casterPlayer && damage.origin != ORIGIN_CONDITION) {
CombatDamage leechCombat;
leechCombat.origin = ORIGIN_NONE;
leechCombat.leeched = true;
int32_t totalDamage = std::abs(damage.primary.value + damage.secondary.value);
if (casterPlayer->getHealth() < casterPlayer->getMaxHealth()) {
uint16_t chance = casterPlayer->getSpecialSkill(SPECIALSKILL_LIFELEECHCHANCE);
uint16_t skill = casterPlayer->getSpecialSkill(SPECIALSKILL_LIFELEECHAMOUNT);
if (chance > 0 && skill > 0 && normal_random(1, 100) <= chance) {
leechCombat.primary.value = std::round(totalDamage * (skill / 100.));
g_game.combatChangeHealth(nullptr, casterPlayer, leechCombat);
casterPlayer->sendMagicEffect(casterPlayer->getPosition(), CONST_ME_MAGIC_RED);
}
}
if (casterPlayer->getMana() < casterPlayer->getMaxMana()) {
uint16_t chance = casterPlayer->getSpecialSkill(SPECIALSKILL_MANALEECHCHANCE);
uint16_t skill = casterPlayer->getSpecialSkill(SPECIALSKILL_MANALEECHAMOUNT);
if (chance > 0 && skill > 0 && normal_random(1, 100) <= chance) {
leechCombat.primary.value = std::round(totalDamage * (skill / 100.));
g_game.combatChangeMana(nullptr, casterPlayer, leechCombat);
casterPlayer->sendMagicEffect(casterPlayer->getPosition(), CONST_ME_MAGIC_BLUE);
}
}
}
if (params.dispelType == CONDITION_PARALYZE) {
target->removeCondition(CONDITION_PARALYZE);
} else {
target->removeCombatCondition(params.dispelType);
}
}
if (params.targetCallback) {
params.targetCallback->onTargetCombat(caster, target);
}
}
void Combat::doAreaCombat(Creature* caster, const Position& position, const AreaCombat* area, CombatDamage& damage, const CombatParams& params)
{
auto tiles = caster ? getCombatArea(caster->getPosition(), position, area) : getCombatArea(position, position, area);
Player* casterPlayer = caster ? caster->getPlayer() : nullptr;
int32_t criticalPrimary = 0;
int32_t criticalSecondary = 0;
if (!damage.critical && damage.primary.type != COMBAT_HEALING && casterPlayer && damage.origin != ORIGIN_CONDITION) {
uint16_t chance = casterPlayer->getSpecialSkill(SPECIALSKILL_CRITICALHITCHANCE);
uint16_t skill = casterPlayer->getSpecialSkill(SPECIALSKILL_CRITICALHITAMOUNT);
if (chance > 0 && skill > 0 && uniform_random(1, 100) <= chance) {
criticalPrimary = std::round(damage.primary.value * (skill / 100.));
criticalSecondary = std::round(damage.secondary.value * (skill / 100.));
damage.critical = true;
}
}
uint32_t maxX = 0;
uint32_t maxY = 0;
//calculate the max viewable range
for (Tile* tile : tiles) {
const Position& tilePos = tile->getPosition();
uint32_t diff = Position::getDistanceX(tilePos, position);
if (diff > maxX) {
maxX = diff;
}
diff = Position::getDistanceY(tilePos, position);
if (diff > maxY) {
maxY = diff;
}
}
const int32_t rangeX = maxX + Map::maxViewportX;
const int32_t rangeY = maxY + Map::maxViewportY;
SpectatorVec spectators;
g_game.map.getSpectators(spectators, position, true, true, rangeX, rangeX, rangeY, rangeY);
postCombatEffects(caster, position, params);
std::vector<Creature*> toDamageCreatures;
toDamageCreatures.reserve(100);
for (Tile* tile : tiles) {
if (canDoCombat(caster, tile, params.aggressive) != RETURNVALUE_NOERROR) {
continue;
}
combatTileEffects(spectators, caster, tile, params);
if (CreatureVector* creatures = tile->getCreatures()) {
const Creature* topCreature = tile->getTopCreature();
for (Creature* creature : *creatures) {
if (params.targetCasterOrTopMost) {
if (caster && caster->getTile() == tile) {
if (creature != caster) {
continue;
}
} else if (creature != topCreature) {
continue;
}
}
if (!params.aggressive || (caster != creature && Combat::canDoCombat(caster, creature) == RETURNVALUE_NOERROR)) {
toDamageCreatures.push_back(creature);
if (params.targetCasterOrTopMost) {
break;
}
}
}
}
}
CombatDamage leechCombat;
leechCombat.origin = ORIGIN_NONE;
leechCombat.leeched = true;
for (Creature* creature : toDamageCreatures) {
CombatDamage damageCopy = damage; // we cannot avoid copying here, because we don't know if it's player combat or not, so we can't modify the initial damage.
bool playerCombatReduced = false;
if ((damageCopy.primary.value < 0 || damageCopy.secondary.value < 0) && caster) {
Player* targetPlayer = creature->getPlayer();
if (casterPlayer && targetPlayer && casterPlayer != targetPlayer && targetPlayer->getSkull() != SKULL_BLACK) {
damageCopy.primary.value /= 2;
damageCopy.secondary.value /= 2;
playerCombatReduced = true;
}
}
if (damageCopy.critical) {
damageCopy.primary.value += playerCombatReduced ? criticalPrimary / 2 : criticalPrimary;
damageCopy.secondary.value += playerCombatReduced ? criticalSecondary / 2 : criticalSecondary;
g_game.addMagicEffect(creature->getPosition(), CONST_ME_BLOODYSTEPS);
}
bool success = false;
if (damageCopy.primary.type != COMBAT_MANADRAIN) {
if (g_game.combatBlockHit(damageCopy, caster, creature, params.blockedByShield, params.blockedByArmor, params.itemId != 0, params.ignoreResistances)) {
continue;
}
success = g_game.combatChangeHealth(caster, creature, damageCopy);
} else {
success = g_game.combatChangeMana(caster, creature, damageCopy);
}
if (success) {
if (damage.blockType == BLOCK_NONE || damage.blockType == BLOCK_ARMOR) {
for (const auto& condition : params.conditionList) {
if (caster == creature || !creature->isImmune(condition->getType())) {
Condition* conditionCopy = condition->clone();
if (caster) {
conditionCopy->setParam(CONDITION_PARAM_OWNER, caster->getID());
}
//TODO: infight condition until all aggressive conditions has ended
creature->addCombatCondition(conditionCopy);
}
}
}
int32_t totalDamage = std::abs(damageCopy.primary.value + damageCopy.secondary.value);
if (casterPlayer && !damage.leeched && damage.primary.type != COMBAT_HEALING && damage.origin != ORIGIN_CONDITION) {
int32_t targetsCount = toDamageCreatures.size();
if (casterPlayer->getHealth() < casterPlayer->getMaxHealth()) {
uint16_t chance = casterPlayer->getSpecialSkill(SPECIALSKILL_LIFELEECHCHANCE);
uint16_t skill = casterPlayer->getSpecialSkill(SPECIALSKILL_LIFELEECHAMOUNT);
if (chance > 0 && skill > 0 && normal_random(1, 100) <= chance) {
leechCombat.primary.value = std::ceil(totalDamage * ((skill / 100.) + ((targetsCount - 1) * ((skill / 100.) / 10.))) / targetsCount);
g_game.combatChangeHealth(nullptr, casterPlayer, leechCombat);
casterPlayer->sendMagicEffect(casterPlayer->getPosition(), CONST_ME_MAGIC_RED);
}
}
if (casterPlayer->getMana() < casterPlayer->getMaxMana()) {
uint16_t chance = casterPlayer->getSpecialSkill(SPECIALSKILL_MANALEECHCHANCE);
uint16_t skill = casterPlayer->getSpecialSkill(SPECIALSKILL_MANALEECHAMOUNT);
if (chance > 0 && skill > 0 && normal_random(1, 100) <= chance) {
leechCombat.primary.value = std::ceil(totalDamage * ((skill / 100.) + ((targetsCount - 1) * ((skill / 100.) / 10.))) / targetsCount);
g_game.combatChangeMana(nullptr, casterPlayer, leechCombat);
casterPlayer->sendMagicEffect(casterPlayer->getPosition(), CONST_ME_MAGIC_BLUE);
}
}
}
if (params.dispelType == CONDITION_PARALYZE) {
creature->removeCondition(CONDITION_PARALYZE);
} else {
creature->removeCombatCondition(params.dispelType);
}
}
if (params.targetCallback) {
params.targetCallback->onTargetCombat(caster, creature);
}
}
}
Last edited: