• 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!

C++ Help Add a delay or interval to extraattack, (trying to mimic old monster behavior) TFS 1.5

Felipe93

Ghost Member
Joined
Mar 21, 2015
Messages
1,990
Solutions
9
Reaction score
334
Location
Chile
Hello

I've working on monsters behavior and I've added extraattack function code, so it will be possible for monsters to attack like monsters did in versions 7.x
for example, hunter massive hits, while being chased or while you're running away... This code works, but the hits are superfast.
Is there a way to set a delay or interval inside the code?

this does not works
Lua:
if (attackedCreature && interval > 100) attackTicks += (interval - 100);

here you can see examples of the actual behavior


Post automatically merged:

Lua:
void Monster::doAttacking(uint32_t interval)
{
    if (!attackedCreature || (isSummon() && attackedCreature == this)) {
        return;
    }

    bool updateLook = true;
    bool outOfRange = true;
    bool resetTicks = interval != 0;
    attackTicks += interval;

    const Position& myPos = getPosition();
    const Position& targetPos = attackedCreature->getPosition();

    for (const spellBlock_t& spellBlock : mType->info.attackSpells) {
        if (spellBlock.isMelee && isFleeing())
            continue;
        bool inRange = false;

        if (attackedCreature == nullptr) {
            break;
        }

        if (canUseSpell(myPos, targetPos, spellBlock, interval, inRange, resetTicks)) {
            if (spellBlock.chance >= static_cast<uint32_t>(uniform_random(1, 100))) {
                if (updateLook) {
                    updateLookDirection();
                    updateLook = false;
                }

                minCombatValue = spellBlock.minCombatValue;
                maxCombatValue = spellBlock.maxCombatValue;
              

                if (spellBlock.isMelee || OTSYS_TIME() > (lastMeleeAttack + interval)) {
                    spellBlock.spell->castSpell(this, attackedCreature);
                    if (isMelee) {
                        extraMeleeAttack = false;
                        lastMeleeAttack = OTSYS_TIME();
                }
            }
        }

            if (inRange) {
                outOfRange = false;
            }
            else if (isMelee && OTSYS_TIME() > (lastMeleeAttack + interval)) {
                //melee swing out of reach
                extraMeleeAttack = true;
                //resetTicks = true;
                //g_game.addAnimatedText(getPosition(), TEXTCOLOR_WHITE_EXP, "Extra melee");
        }
    }
    }
    if (attackedCreature && interval > 100) attackTicks += (interval - 100);

    if (updateLook) {
        updateLookDirection();
    }

    if (resetTicks) {
        attackTicks = 0;
    }
}

Code:
bool Monster::getDanceStep(const Position& creaturePos, Direction& direction,
                           bool keepAttack /*= true*/, bool keepDistance /*= true*/)
{
    bool canDoAttackNow = canUseAttack(creaturePos, attackedCreature);

    assert(attackedCreature != nullptr);
    const Position& centerPos = attackedCreature->getPosition();

    int_fast32_t offset_x = Position::getOffsetX(creaturePos, centerPos);
    int_fast32_t offset_y = Position::getOffsetY(creaturePos, centerPos);

    int_fast32_t distance_x = std::abs(offset_x);
    int_fast32_t distance_y = std::abs(offset_y);

    uint32_t centerToDist = std::max<uint32_t>(distance_x, distance_y);

    std::vector<Direction> dirList;
    dirList.reserve(4);

    if (!keepDistance || offset_y >= 0) {
        uint32_t tmpDist = std::max<uint32_t>(distance_x, std::abs((creaturePos.getY() - 1) - centerPos.getY()));
        if (tmpDist == centerToDist && canWalkTo(creaturePos, DIRECTION_NORTH)) {
            bool result = true;

            if (keepAttack) {
                result = (!canDoAttackNow || canUseAttack(Position(creaturePos.x, creaturePos.y - 1, creaturePos.z), attackedCreature));
                extraMeleeAttack = true;
            }

            if (result) {
                dirList.push_back(DIRECTION_NORTH);
            }
        }
    }

    if (!keepDistance || offset_y <= 0) {
        uint32_t tmpDist = std::max<uint32_t>(distance_x, std::abs((creaturePos.getY() + 1) - centerPos.getY()));
        if (tmpDist == centerToDist && canWalkTo(creaturePos, DIRECTION_SOUTH)) {
            bool result = true;

            if (keepAttack) {
                result = (!canDoAttackNow || canUseAttack(Position(creaturePos.x, creaturePos.y + 1, creaturePos.z), attackedCreature));
                extraMeleeAttack = true;
            }

            if (result) {
                dirList.push_back(DIRECTION_SOUTH);
            }
        }
    }

    if (!keepDistance || offset_x <= 0) {
        uint32_t tmpDist = std::max<uint32_t>(std::abs((creaturePos.getX() + 1) - centerPos.getX()), distance_y);
        if (tmpDist == centerToDist && canWalkTo(creaturePos, DIRECTION_EAST)) {
            bool result = true;

            if (keepAttack) {
                result = (!canDoAttackNow || canUseAttack(Position(creaturePos.x + 1, creaturePos.y, creaturePos.z), attackedCreature));
                extraMeleeAttack = true;
            }

            if (result) {
                dirList.push_back(DIRECTION_EAST);
            }
        }
    }

    if (!keepDistance || offset_x >= 0) {
        uint32_t tmpDist = std::max<uint32_t>(std::abs((creaturePos.getX() - 1) - centerPos.getX()), distance_y);
        if (tmpDist == centerToDist && canWalkTo(creaturePos, DIRECTION_WEST)) {
            bool result = true;

            if (keepAttack) {
                result = (!canDoAttackNow || canUseAttack(Position(creaturePos.x - 1, creaturePos.y, creaturePos.z), attackedCreature));
                extraMeleeAttack = true;
            }

            if (result) {
                dirList.push_back(DIRECTION_WEST);
            }
        }
    }

    if (!dirList.empty()) {
        std::shuffle(dirList.begin(), dirList.end(), getRandomGenerator());
        direction = dirList[uniform_random(0, dirList.size() - 1)];
        return true;
    }
    return false;
}
 
Last edited:
I think it is wrong behaviour. As far as I can remember, in 7.x creatures where using spells everytime the interval hits + everytime that Creature moves, not the player. So it should work like this: Creature is going through spells and if RNG hits chance the creature use spell and ads interval, but if creature moves 1 sqm, the interval is reset and creature is going through spells again. Probably Kay or Ezzz know better how it should work. You can also find Tibiantis development thread - it should be explained there too.
 
Back
Top