• There is NO official Otland's Discord server and NO official Otland's server list. The Otland's Staff does not manage any Discord server or server list. Moderators or administrator of any Discord server or server lists have NO connection to the Otland's Staff. Do not get scammed!

Exeta amp res dont work TFS 1.5 downgrade

Azerty

Active Member
Joined
Apr 15, 2022
Messages
316
Solutions
4
Reaction score
32
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

bandicam 2023-04-12 07-51-26-005.gif
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:
Back
Top