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

OTClient 1.0

It's due to wrong top thing probably. Instead of removing m_things we should still use it and recache it only in draw function.
At the start of Tile::draw:
C++:
    if(isEmpty())
        return;

    if(m_needsRedraw) {
        cacheThings();
        m_needsRedraw = false;
    }

m_needsRedraw = true; only in functions of addThing and removeThing after m_things.erase and insert.

C++:
void Tile::cacheThings()
{
    m_firstBottomItems.clear();
    m_topItems.clear();
    m_commonItems.clear();
    m_creatures.clear();

    for(auto it = m_things.begin(), end(m_things.end()); it != end; ++it) {
        const ThingPtr& thing = *it;
        if(thing->isGround() || thing->isGroundBorder() || thing->isOnBottom()) {
            m_firstBottomItems.push_back(thing);
        }
        else if(thing->isOnTop())
            m_topItems.push_back(thing);
        else if(!thing->isCreature())
            m_commonItems.push_back(thing);
        }
        else
        {
            CreaturePtr creature = thing->static_self_cast<Creature>();
            m_creatures.push_back(creature);
        }
    }
}

So now we can draw like:
C++:
    // top items
    if(drawFlags & Otc::DrawOnTop) {
        for(auto it = m_topItems.begin(), end(m_topItems.end()); it != end; ++it) {
            const ThingPtr& thing = *it;
            thing->draw(dest, scaleFactor, animate, lightView);
        }
    }
etc.
 
Have you got maybe solution to this? 🤔

Replace this function inside tile.cpp
C++:
ThingPtr Tile::getTopUseThing()

With
C++:
ThingPtr Tile::getTopUseThing() {
    if (!m_commonItems.empty()) return m_commonItems[0];

    for (auto thing : m_things) {
        if (thing->isForceUse() || (!thing->isGround() && !thing->isGroundBorder() && !thing->isOnBottom() && !thing->isOnTop() && !thing->isCreature() && !thing->isSplash()))
            return thing;
    }

    for (auto thing : m_things) {
        if (!thing->isGround() && !thing->isGroundBorder() && !thing->isCreature() && !thing->isSplash())
            return thing;
    }

    if (!m_creatures.empty()) return m_creatures[0];
    return m_things[0];
}

Source: stock OTC
 
Replace this function inside tile.cpp
C++:
ThingPtr Tile::getTopUseThing()

With
C++:
ThingPtr Tile::getTopUseThing() {
    if (!m_commonItems.empty()) return m_commonItems[0];

    for (auto thing : m_things) {
        if (thing->isForceUse() || (!thing->isGround() && !thing->isGroundBorder() && !thing->isOnBottom() && !thing->isOnTop() && !thing->isCreature() && !thing->isSplash()))
            return thing;
    }

    for (auto thing : m_things) {
        if (!thing->isGround() && !thing->isGroundBorder() && !thing->isCreature() && !thing->isSplash())
            return thing;
    }

    if (!m_creatures.empty()) return m_creatures[0];
    return m_things[0];
}

Source: stock OTC
Why are you iterating same array twice?
 
all objects are in this m_things vector, but it is deprecated
But that doesn't answer my question.

This would be more sufficient.
C++:
    for (auto thing : m_things) {
        if (thing->isForceUse() || (!thing->isGround() && !thing->isGroundBorder() && !thing->isOnBottom() && !thing->isOnTop() && !thing->isCreature() && !thing->isSplash()))
            return thing;
        if (!thing->isGround() && !thing->isGroundBorder() && !thing->isCreature() && !thing->isSplash())
            return thing;
    }
 
But that doesn't answer my question.

This would be more sufficient.
C++:
    for (auto thing : m_things) {
        if (thing->isForceUse() || (!thing->isGround() && !thing->isGroundBorder() && !thing->isOnBottom() && !thing->isOnTop() && !thing->isCreature() && !thing->isSplash()))
            return thing;
        if (!thing->isGround() && !thing->isGroundBorder() && !thing->isCreature() && !thing->isSplash())
            return thing;
    }

In short, I say to ignore the old code, but since you want an explanation of having two "for" the same vector, it is for the simple fact that order matters.

1- Force Use Thing
2- Common Items
3- Bottom Items
4- Ground
 
Last edited:
We should address the DX9 compilation with VS2019 as well.

Why are you iterating same array twice?

I'm not, I just took it from OTC source. Such double loop doesn't make any harm at all, it just looks bad but maybe the compiler itself optimizes it together, tiles on OTC only hold 10 objects per tile, such loop would take much less than a fraction of a millisecond to even notice any harm.
 
Last edited:
I don't know if it's bug or not (but this occured after Mehah fixes) :

I can't simply throw items on surface under items (tree leaves that covering surface but they are on +1 floor) that are on upper floor.
Video: Click to Watch!
Screen from Map Editor: Click to See!
If it's meant to be like that (can't move items on same floor under items that are on upper floor), can anyone help me to remove that and get possibility to move items on same floor under items on upper floor? 🤔 (As I said above, I had this opportunity before the @Mehah fixes).

#Edit:
Tested with creating items "under my specific tree with leaves on upper floor", and can't move items when they are covered by items on upper floor.
[ WATCH ] :: Can't move items that are covered by other items on upper floor.

:rolleyes: o_O

I should experiment with ObjectBuilder and flags in Items (those one on upper floor - tree leaves) or ...?
 
Last edited:
I don't know if it's bug or not (but this occured after Mehah fixes) :

I can't simply throw items on surface under items (tree leaves that covering surface but they are on +1 floor) that are on upper floor.
Video: Click to Watch!
Screen from Map Editor: Click to See!
If it's meant to be like that (can't move items on same floor under items that are on upper floor), can anyone help me to remove that and get possibility to move items on same floor under items on upper floor? 🤔 (As I said above, I had this opportunity before the @Mehah fixes).

#Edit:
Tested with creating items "under my specific tree with leaves on upper floor", and can't move items when they are covered by items on upper floor.
[ WATCH ] :: Can't move items that are covered by other items on upper floor.

:rolleyes: o_O

I should experiment with ObjectBuilder and flags in Items (those one on upper floor - tree leaves) or ...?

plz

1- Use GIT to report
2- Make sure you are using the latest revision and without modifying in source code.

Sorry, but I couldn't understand anything with this video, I need you to simulate the problem in Tibia, because it is the only place that I will also be able to simulate and test.

Thx
 
We can use switch & case here:
C++:
ViewportControl::ViewportControl(const Otc::Direction directionWalking)
{
    m_top = maxViewportY;
    m_right = maxViewportX;
    m_bottom = m_top;
    m_left = m_right;

    switch(directionWalking) {
        case Otc::North:
            m_top += 1;
            m_bottom += 1;
            break;
        case Otc::East:
            m_right += 1;
            m_left += 1;
            break;
    ...
        case Otc::InvalidDirection:
            break;
    }
}

Also in isValid function we should use translated pos:
C++:
bool ViewportControl::isValid(const TilePtr& tile, const Position cameraPosition) const
{
    const Position tilePos = tile->getPosition();
    const int dz = tilePos.z - cameraPosition.z;
    Position checkPos = tilePos.translated(dz, dz);

    if(cameraPosition.x - checkPos.x >= m_left || cameraPosition.y - checkPos.y >= m_top)
        return false;
    else if((checkPos.x - cameraPosition.x >= m_right || checkPos.y - cameraPosition.y >= m_bottom) && tile->isSingleDimension())
        return false;

    return true;
}
 
View attachment 47041

Hey Mehah.. not is the same shit? 🤔
In this case yes, post-increment creates copy of current value so if it is possible to avoid it by using pre-increment you can save some cpu cycles by avoiding some move instructions, however since this case doesn't need that copy it should be optimized away to the same assembly code.
 
As promised, it follows the optimization on name and life bar.

Old Version:
normal.png

Tile Optimized Version:
op1.png

Tile, name and lifebar optimized Version:
op2.png

On Battle:

It is still possible to optimize much more, because the name and life bar, are being rendered in the same frame, other things that we can do, is the floors have their own frames.

Ahhh not forgetting, static and animated messages were not optimized.
 
Last edited:
As promised, it follows the optimization on name and life bar.

Old Version:
View attachment 47071

Tile Optimized Version:
View attachment 47072

Tile, name and lifebar optimized Version:
View attachment 47073

On Battle:

It is still possible to optimize much more, because the name and life bar, are being rendered in the same frame, other things that we can do, is the floors have their own frames.

Ahhh not forgetting, static and animated messages were not optimized.
damm people will start using official otc again very good man keep it up!
 
Back
Top