• 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++ monster ranged attack tfs 1.5 are very off is there a way to fix this?

Diarreamental

Banned User
Joined
Jul 6, 2015
Messages
463
Solutions
1
Reaction score
85
Hello

As stated in the title ranged attack are off like gfb , spears or any ranged attack made by monsters

doing a research i found that nostarlius based off tfs 1.2 was having or has this problem too, they have fixed it by changing normal_random to unfirom_random in sources Nostalrius 7.7 (https://otland.net/threads/nostalrius-7-7.262406/page-18)
the code is this:
LUA:
void Monster::onThinkDefense(uint32_t)
{
    for (const spellBlock_t& spellBlock : mType->info.defenseSpells) {
        if (uniform_random(0, spellBlock.chance) == 0 && (master || health > mType->info.runAwayHealth || uniform_random(1, 3) == 1)) {
            minCombatValue = spellBlock.minCombatValue;
            maxCombatValue = spellBlock.maxCombatValue;
            spellBlock.spell->castSpell(this, this);
        }
    }

    if (!isSummon() && summons.size() < mType->info.maxSummons && hasFollowPath) {
        for (const summonBlock_t& summonBlock : mType->info.summons) {
            if (summons.size() >= mType->info.maxSummons) {
                continue;
            }

            uint32_t summonCount = 0;
            for (Creature* summon : summons) {
                if (summon->getName() == summonBlock.name) {
                    ++summonCount;
                }
            }

            if (summonCount >= summonBlock.max) {
                continue;
            }

            if (uniform_random(0, summonBlock.chance) == 0 && (health > mType->info.runAwayHealth || uniform_random(1, 3) == 1)) {
                Monster* summon = Monster::createMonster(summonBlock.name);
                if (summon) {
                    const Position& summonPos = getPosition();

                    addSummon(summon);

                    if (!g_game.placeCreature(summon, summonPos, false, summonBlock.force)) {
                        removeSummon(summon);
                    } else {
                        g_game.addMagicEffect(getPosition(), CONST_ME_MAGIC_BLUE);
                        g_game.addMagicEffect(summon->getPosition(), CONST_ME_TELEPORT);
                    }
                }
            }
        }
    }
}
the other part:
Code:
void Monster::doAttacking(uint32_t)
{
    if (!attackedCreature || (isSummon() && attackedCreature == this)) {
        return;
    }

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

    bool updateLook = false;

    if (OTSYS_TIME() >= earliestAttackTime && !isFleeing()) {
        updateLook = true;
        if (Combat::closeAttack(this, attackedCreature, FIGHTMODE_BALANCED)) {
            egibleToDance = true;
            earliestAttackTime = OTSYS_TIME() + 2000;
            removeCondition(CONDITION_AGGRESSIVE, true);
        }
    }

    for (spellBlock_t& spellBlock : mType->info.attackSpells) {
        if (spellBlock.range != 0 && std::max<uint32_t>(Position::getDistanceX(myPos, targetPos), Position::getDistanceY(myPos, targetPos)) <= spellBlock.range) {
            if (uniform_random(0, spellBlock.chance) == 0 && (master || health > mType->info.runAwayHealth || uniform_random(1, 3) == 1)) {
                updateLookDirection();

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

                spellBlock.spell->castSpell(this, attackedCreature);
                egibleToDance = true;
            }
        }
    }

    if (updateLook) {
        updateLookDirection();
    }
}

the code is a bit different in tfs 1.5 qnd seems to be "fixed" but it isn't. as i stated in the main title the ranged attacks are very off in comparision with othire or tfs 0.4

here is the code
Code:
void Monster::doAttacking(uint32_t interval)
{
    if (!attackedCreature || (isSummon() && attackedCreature == this)) {
        return;
    }

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

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

    for (const spellBlock_t& spellBlock : mType->info.attackSpells) {
        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;
                spellBlock.spell->castSpell(this, attackedCreature);

                if (spellBlock.isMelee) {
                    lastMeleeAttack = OTSYS_TIME();
                }
            }
        }

        if (!inRange && spellBlock.isMelee) {
            //melee swing out of reach
            lastMeleeAttack = 0;
        }
    }

    if (updateLook) {
        updateLookDirection();
    }

    if (resetTicks) {
        attackTicks = 0;
    }
}

the other part
Code:
void Monster::onThinkDefense(uint32_t interval)
{
    bool resetTicks = true;
    defenseTicks += interval;

    for (const spellBlock_t& spellBlock : mType->info.defenseSpells) {
        if (spellBlock.speed > defenseTicks) {
            resetTicks = false;
            continue;
        }

        if (defenseTicks % spellBlock.speed >= interval) {
            //already used this spell for this round
            continue;
        }

        if ((spellBlock.chance >= static_cast<uint32_t>(uniform_random(1, 100)))) {
            minCombatValue = spellBlock.minCombatValue;
            maxCombatValue = spellBlock.maxCombatValue;
            spellBlock.spell->castSpell(this, this);
        }
    }

    if (!isSummon() && summons.size() < mType->info.maxSummons && hasFollowPath) {
        for (const summonBlock_t& summonBlock : mType->info.summons) {
            if (summonBlock.speed > defenseTicks) {
                resetTicks = false;
                continue;
            }

            if (summons.size() >= mType->info.maxSummons) {
                continue;
            }

            if (defenseTicks % summonBlock.speed >= interval) {
                //already used this spell for this round
                continue;
            }

            uint32_t summonCount = 0;
            for (Creature* summon : summons) {
                if (summon->getName() == summonBlock.name) {
                    ++summonCount;
                }
            }

            if (summonCount >= summonBlock.max) {
                continue;
            }

            if (summonBlock.chance < static_cast<uint32_t>(uniform_random(1, 100))) {
                continue;
            }

            Monster* summon = Monster::createMonster(summonBlock.name);
            if (summon) {
                if (g_game.placeCreature(summon, getPosition(), false, summonBlock.force)) {
                    summon->setDropLoot(false);
                    summon->setSkillLoss(false);
                    summon->setMaster(this);
                    g_game.addMagicEffect(getPosition(), CONST_ME_MAGIC_BLUE);
                    g_game.addMagicEffect(summon->getPosition(), CONST_ME_TELEPORT);
                } else {
                    delete summon;
                }
            }
        }
    }

    if (resetTicks) {
        defenseTicks = 0;
    }
}

can somebody point out what to change or how to?

thank
 
As stated in the title ranged attack are off like gfb , spears or any ranged attack made by monsters
Hi! Is there a chance that you could record the behaviour? And if possible have a reference of how should behave. I'm not good at c++ hope that @Itutorial take a look into it, this way the a* can be improved more, for what I can say a recording could speed up the fix. Regards!
 
mp4: OldschoolWar - Blex 2022-10-28 08-35-57.mp4 (https://files.fm/u/2d7x6ftjz) there i explain everything and can be easily observed

}
when a player reaches a monster that attack from distance this monster just stand still and stop walking almost every 2 seconds then stop again attack and walk 1 sqm then attack and repeat this over and over, the monster can gain distance once the player have stop chasing the monster ( monster need 2 sqm to behave normally again)
@ralke
sorry if i can't upload the video to youtube my account has been banned because it was hacked

the same problem occurs for mosnter heal and magic attacks
 
Last edited:
mp4: OldschoolWar - Blex 2022-10-28 08-35-57.mp4 (https://files.fm/u/2d7x6ftjz) there i explain everything and can be easily observed

}
when a player reaches a monster that attack from distance this monster just stand still and stop walking almost every 2 seconds then stop again attack and walk 1 sqm then attack and repeat this over and over, the monster can gain distance once the player have stop chasing the monster ( monster need 2 sqm to behave normally again)
@ralke
sorry if i can't upload the video to youtube my account has been banned because it was hacked

the same problem occurs for mosnter heal and magic attacks
I couldn't record RL tibia, not sure why. But it behaves the same when i'm in close range (this means it has the correct behaviour), anyone can confirm? For what I see everything works like it should. I used my real tibia character to check with Orc Spearmeans.
 
Sad but true ATM. although with this new code monster ar working way better than they used to. Anyway in TFS 0.4 the monste behavior is bad too u.u
The code works well, I don't see anything wrong. Check your videos and compare to this one I recorded on real-tibia:
 
The code works well, I don't see anything wrong. Check your videos and compare to this one I recorded on real-tibia:
check how behave monster like fire devil witch warlock hunter they barely attack(shoot spells)when they are being chased, they just hit melee
 
up
meant something like this "Ranged monsters execute actions every 1 seconds at a distance, as well as take an extra attack while stepping. Because of this, they are more likely to combo/spam attacks while running towards/away from you
 
Sad but true ATM. although with this new code monster ar working way better than they used to. Anyway in TFS 0.4 the monste behavior is bad too u.u
"Anyway in TFS 0.4 the monste behavior is bad too u.u"
No, it isn't if we are talking about the AI, not CPU consumption. They are as reactive as they can be in any TFS.
OTX 2 (something like 0.4) (situation on image):
1670424335689.png
is taking 4 up to 4,5% of CPU.
---
If you apply available fixes to e.g. tfs 1.4.2 to get the exact same effect as it is on otx you would be using (based on gesior's benchmarking):
Algo nr 4 with 15 demons: 5.12% CPU
5.12% with 15 demons...
 
I've done more investigation regarding this and went into the RealOTS server hoster by @pink_panther and recorded a session with Hunter. Just standing there and taking damage.
@ralke @Itutorial Please watch the entire video below to understand it correctly.

I then went into TFS 1.5 Downgrade from @Nekiro which can be found here: GitHub - nekiro/TFS-1.5-Downgrades at 8.0 (https://github.com/nekiro/TFS-1.5-Downgrades/tree/8.0). I recorded a video with a hunter there and this is the result:


I noticed that in Real Tibia and RealOTS which is Real Tibia, hunters and other "spell" casters have a chance to shoot another projective instantly after the first projective. Instead, in TFS, it casts, waits, casts, etc... There is no possible way to as they call it "machine gun hunter". @kay Perhaps you have a better video of when a hunter spams, I went to your old Tibiantis post where you had a gif but that disappeared.


This is when I chase the hunter on RealOTS:

This is when I chase the hunter in TFS 1.5 Downgrade By Nekiro:

There is obviously a very very big difference.

I found similar issues that people reported and found this solution:

But it does not work.
 
Last edited:
I found similar issues that people reported and found this solution:

But it does not work.
That solution has nothing to do with it. It only changes normal distribution to uniform.
It's nothing new, tfs has never been accurate to the real tibia to say the least, and there's no easy fix for this. It just works differently in many aspects. Also, if anything, it aims to mimic the current versions of tibia by default, and afaik that behavior was changed somewhere around 8.0~.
 
That solution has nothing to do with it. It only changes normal distribution to uniform.
It's nothing new, tfs has never been accurate to the real tibia to say the least, and there's no easy fix for this. It just works differently in many aspects. Also, if anything, it aims to mimic the current versions of tibia by default, and afaik that behavior was changed somewhere around 8.0~.

I love that effect, it feels more logical that a creature should be able to spam you when you run towards it.

I'd appreciate it if someone could help with this. Or at least guide me towards where to look and how to think regarding this.
 
I love that effect, it feels more logical that a creature should be able to spam you when you run towards it.

I'd appreciate it if someone could help with this. Or at least guide me towards where to look and how to think regarding this.
I think this could be approached more with a spell for the monster, than editing the sources. You just have one attack pointed as melee on hunters right? The monsters are not always 100% accurate, we have the approach from TibiaWiki, but nothing says that you can't add more attacks than this:

XML:
    <attacks>
        <attack name="melee" interval="2000" min="0" max="-20" />
        <attack name="physical" interval="2000" chance="50" range="7" min="0" max="-100">
            <attribute key="shootEffect" value="arrow" />
        </attack>
    </attacks>

I mean, you can craft more than those two physical/melee attacks and elaborate using custom cooldowns and stuff. Pathfinding has nothing to do with cooldowns (or probably has to do, is needed to define that approach and where in the sources it is located), the monster looks better and more responsive at the downgrade in terms of pathfinding, making routes, etc. Hope this helps, regards!
 

Similar threads

Back
Top