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

Client crashes 10.98. Latest TFS.

Simonalina

Member
Joined
May 10, 2008
Messages
180
Solutions
1
Reaction score
15
Location
Sweden
Error Report full.png
everytime i get crash, this is exacly the same window that pop ups.. (most of time when im doing a spel, but also when im just running without attacking)

does anyone know what it means?

network.cpp
control.cpp
Communcation.cpp
map.cpp


and this Bug 0000013
Im woundering if it has to do with what it say? MAPSIZE_X-1? <-- wrong with map size?

im using TFS latest items.otb/xml
Yes i made "Cleanup" in mapeditor.
 
player position: 32774, 32255, 7

last packet from server: DISTANCE SHOT ANIMATION (first byte is 133 = 0x85)
from: 32784,32255,7 (10 tiles away in x-axis)
to: 32785,32256,7 (11 tiles away in x-axis)
effect: 4 (CONST_ANI_FIRE)

Client debug reason: animation is too far (not on player screen!)

In magic effect code, there is range limit ('canSee' checks if position is visible on player screen):
Code:
void ProtocolGame::sendMagicEffect(const Position& pos, uint8_t type)
{
    if (!canSee(pos)) {
        return;
    }
    (...)

In distance effect, there is no checks. It just send it to client:
Code:
void ProtocolGame::sendDistanceShoot(const Position& from, const Position& to, uint8_t type)
{
    NetworkMessage msg;
    msg.addByte(0x85);
I don't know, if there was 'canSee' before or there was some other code, that protect server from sending animation off screen.
 
player position: 32774, 32255, 7

last packet from server: DISTANCE SHOT ANIMATION (first byte is 133 = 0x85)
from: 32784,32255,7 (10 tiles away in x-axis)
to: 32785,32256,7 (11 tiles away in x-axis)
effect: 4 (CONST_ANI_FIRE)

Client debug reason: animation is too far (not on player screen!)

In magic effect code, there is range limit ('canSee' checks if position is visible on player screen):
Code:
void ProtocolGame::sendMagicEffect(const Position& pos, uint8_t type)
{
    if (!canSee(pos)) {
        return;
    }
    (...)

In distance effect, there is no checks. It just send it to client:
Code:
void ProtocolGame::sendDistanceShoot(const Position& from, const Position& to, uint8_t type)
{
    NetworkMessage msg;
    msg.addByte(0x85);
I don't know, if there was 'canSee' before or there was some other code, that protect server from sending animation off screen.
So maybe Evil puncker changed something? this server is his Orts, with latest tfs 1.3..

anyway, do you have any clue how to fix this maybe? right now im trying another map to se if that helps..
 
Replace:
Code:
void ProtocolGame::sendDistanceShoot(const Position& from, const Position& to, uint8_t type)
{
    NetworkMessage msg;
    msg.addByte(0x85);
with:
Code:
void ProtocolGame::sendDistanceShoot(const Position& from, const Position& to, uint8_t type)
{
    if (!canSee(from) || !canSee(to)) {
        return;
    }

    NetworkMessage msg;
    msg.addByte(0x85);
it should fix debug problem.
 
Replace:
Code:
void ProtocolGame::sendDistanceShoot(const Position& from, const Position& to, uint8_t type)
{
    NetworkMessage msg;
    msg.addByte(0x85);
with:
Code:
void ProtocolGame::sendDistanceShoot(const Position& from, const Position& to, uint8_t type)
{
    if (!canSee(from) || !canSee(to)) {
        return;
    }

    NetworkMessage msg;
    msg.addByte(0x85);
it should fix debug problem.
Sorry for my extremly bad scripting. But which file is it in?
Post automatically merged:

i did find this?

Lua:
void ProtocolGame::sendDistanceShoot(const Position& from, const Position& to, uint8_t type)
{
    NetworkMessage msg;
    msg.addByte(0x85);
    msg.addPosition(from);
    msg.addPosition(to);
    msg.addByte(type);
    writeToOutputBuffer(msg);
}
 
Last edited:
Lua:
void ProtocolGame::sendDistanceShoot(const Position& from, const Position& to, uint8_t type)
{
    if (!canSee(from) || !canSee(to)) {
        return;
    }

    NetworkMessage msg;
    msg.addByte(0x85);
    msg.addPosition(from);
    msg.addPosition(to);
    msg.addByte(type);
    writeToOutputBuffer(msg);
}
 
That one didn't help. :(
last packet from server: DISTANCE SHOT ANIMATION (first byte is 133 = 0x85)
from: 32784,32255,7 (10 tiles away in x-axis)
to: 32785,32256,7 (11 tiles away in x-axis)
effect: 4 (CONST_ANI_FIRE)

Client debug reason: animation is too far (not on player screen!)

In magic effect code, there is range limit ('canSee' checks if position is visible on player screen):
Code:
void ProtocolGame::sendMagicEffect(const Position& pos, uint8_t type)
{
    if (!canSee(pos)) {
        return;
    }
    (...)

In distance effect, there is no checks. It just send it to client:
Code:
void ProtocolGame::sendDistanceShoot(const Position& from, const Position& to, uint8_t type)
{
    NetworkMessage msg;
    msg.addByte(0x85);
I don't know, if there was 'canSee' before or there was some other code, that protect server from sending animation off screen.
maybe im new to this, but instead of adding
Lua:
    if (!canSee(pos)) {

        return;
can't i change this Animation?

Becaus now i just get Random errors but all error is the same:

Communation.cpp 2700
Map.cpp 378
it seems like this is more "go through this"

Is there any other way to solve this than to do so?
because I'm thinking a bit that somewhere this error must occur, right?
 
Last edited:
I was just talking to the epunker about this problem, I had a debug with one of my logged characters when using a spell on another, but I couldn't reproduce it again.
try to get "Print screen" of Crash log when you open Tibia next time, if it's the same problem with bug "00000013"

Then maybe someone who knows could fix it for all of us who really want this TFS 1.3 to work good :)

So far i tried
5 things:
Changed something in Gameprotocoll.cpp and rebuilded..
Changed tibia client (Tried 3 diffrent)
Changed Map (3 Different Realmaps)
Changed Items.otb/ and XML..
Cleanup in Mapeditor (Also exacly the same "items.otb" file as server")

Post automatically merged:

UPDATE!!!!

So i made a new map with "Bats" and me and my friend run around.. we got Crash...

THEN

I made an empty map... just grass without monsters.... and didn't Get crash...

so.. one thing for sure is that the MONSTERS... is doing all this!


@Gesior.pl @Evil Puncker
 
Last edited:
Try to capture more tibia client crash logs (make screens of bug report after client restart). Last error you reported clearly says that position is off screen and server somehow sent it to client.
There are 2 possible reasons:
  • not compatible dat/otb
  • something in c++ is bugged

It's often easier to detect these bugs using OTC / OTCv8 as it does not crash. It report wrong packets in console and still tries to render game.
 
Try to capture more tibia client crash logs (make screens of bug report after client restart). Last error you reported clearly says that position is off screen and server somehow sent it to client.
There are 2 possible reasons:
  • not compatible dat/otb
  • something in c++ is bugged

It's often easier to detect these bugs using OTC / OTCv8 as it does not crash. It report wrong packets in console and still tries to render game.
Ok, how do i make sure to get an compatible dat/otb to the server? Maybe i can try with that if there is some guide how to make that? :)

( it's always the same error, just diffrent spawn positions )
 
Ok, how do i make sure to get an compatible dat/otb to the server? Maybe i can try with that if there is some guide how to make that? :)

( it's always the same error, just diffrent spawn positions )
I got no idea. Never worked on dat/otb. There are some programs to edit dat/otb and maybe one of them got option to verify that both files have same values for items. Important things are 'stackable' and 'charges' (runes in old clients) attribute. They affect game protocol and may result in error in next random packet.
 
I got no idea. Never worked on dat/otb. There are some programs to edit dat/otb and maybe one of them got option to verify that both files have same values for items. Important things are 'stackable' and 'charges' (runes in old clients) attribute. They affect game protocol and may result in error in next random packet.
Yea im gonna try to figure something out on that, it could be good to have a "quick" guide how to make everything compatible with server, so if I found out i will make a thread just about this haha..
 
I got no idea. Never worked on dat/otb. There are some programs to edit dat/otb and maybe one of them got option to verify that both files have same values for items. Important things are 'stackable' and 'charges' (runes in old clients) attribute. They affect game protocol and may result in error in next random packet.
that is the weird thing we are experiencing, both server and client are using unedited ("original") files (default tfs items.otb for both map and server, default tibia 10.98 client files), everything works well on RME, but once we get ingame doing random things or going to specific places we get a client crash, and I don't think its related to source code at all since the datapack is being used with master-tfs and there is no debug when using another map or so


here are some OTC logs that I gathered:

SPOILER_2021-02-16_18_44_45-OTCv8_-_Perflex.png


2021-02-16-17_30_45-png.png
 
But propably the error is becaus of monsters isnt in my Window? They are moving outside my "screen"? Am i right?
Becaus it never hapens when I play alone or if im in a city without monsters, so is there any way to change this?

And how do you see those errors evil? Got some program or something? :)
 
Code:
//send to client
    size_t i = 0;
    for (Creature* spectator : spectators) {
        if (Player* tmpPlayer = spectator->getPlayer()) {
            //Use the correct stackpos
            int32_t stackpos = oldStackPosVector[i++];
            if (stackpos != -1) {
                tmpPlayer->sendCreatureMove(&creature, newPos, newTile.getClientIndexOfCreature(tmpPlayer, &creature), oldPos, stackpos, teleport);
            }
        }
    }

    //event method
    for (Creature* spectator : spectators) {
        spectator->onCreatureMove(&creature, &newTile, newPos, &oldTile, oldPos, teleport);
    }

    oldTile.postRemoveNotification(&creature, &newTile, 0);
    newTile.postAddNotification(&creature, &oldTile, 0);
}

void Map::getSpectatorsInternal(SpectatorVec& spectators, const Position& centerPos, int32_t minRangeX, int32_t maxRangeX, int32_t minRangeY, int32_t maxRangeY, int32_t minRangeZ, int32_t maxRangeZ, bool onlyPlayers) const
{
    int_fast16_t min_y = centerPos.y + minRangeY;
    int_fast16_t min_x = centerPos.x + minRangeX;
    int_fast16_t max_y = centerPos.y + maxRangeY;
    int_fast16_t max_x = centerPos.x + maxRangeX;

    int32_t minoffset = centerPos.getZ() - maxRangeZ;
    uint16_t x1 = std::min<uint32_t>(0xFFFF, std::max<int32_t>(0, (min_x + minoffset)));
    uint16_t y1 = std::min<uint32_t>(0xFFFF, std::max<int32_t>(0, (min_y + minoffset)));

    int32_t maxoffset = centerPos.getZ() - minRangeZ;
    uint16_t x2 = std::min<uint32_t>(0xFFFF, std::max<int32_t>(0, (max_x + maxoffset)));
    uint16_t y2 = std::min<uint32_t>(0xFFFF, std::max<int32_t>(0, (max_y + maxoffset)));

    int32_t startx1 = x1 - (x1 % FLOOR_SIZE);
    int32_t starty1 = y1 - (y1 % FLOOR_SIZE);
    int32_t endx2 = x2 - (x2 % FLOOR_SIZE);
    int32_t endy2 = y2 - (y2 % FLOOR_SIZE);

    const QTreeLeafNode* startLeaf = QTreeNode::getLeafStatic<const QTreeLeafNode*, const QTreeNode*>(&root, startx1, starty1);
    const QTreeLeafNode* leafS = startLeaf;
    const QTreeLeafNode* leafE;

    for (int_fast32_t ny = starty1; ny <= endy2; ny += FLOOR_SIZE) {
        leafE = leafS;
        for (int_fast32_t nx = startx1; nx <= endx2; nx += FLOOR_SIZE) {
            if (leafE) {
                const CreatureVector& node_list = (onlyPlayers ? leafE->player_list : leafE->creature_list);
                for (Creature* creature : node_list) {
                    const Position& cpos = creature->getPosition();
                    if (minRangeZ > cpos.z || maxRangeZ < cpos.z) {
                        continue;
                    }

                    int_fast16_t offsetZ = Position::getOffsetZ(centerPos, cpos);
                    if ((min_y + offsetZ) > cpos.y || (max_y + offsetZ) < cpos.y || (min_x + offsetZ) > cpos.x || (max_x + offsetZ) < cpos.x) {
                        continue;
                    }

                    spectators.emplace_back(creature);
                }
                leafE = leafE->leafE;
            } else {
                leafE = QTreeNode::getLeafStatic<const QTreeLeafNode*, const QTreeNode*>(&root, nx + FLOOR_SIZE, ny);
            }
        }

        if (leafS) {
            leafS = leafS->leafS;
        } else {
            leafS = QTreeNode::getLeafStatic<const QTreeLeafNode*, const QTreeNode*>(&root, startx1, ny + FLOOR_SIZE);
        }
    }
}

void Map::getSpectators(SpectatorVec& spectators, const Position& centerPos, bool multifloor /*= false*/, bool onlyPlayers /*= false*/, int32_t minRangeX /*= 0*/, int32_t maxRangeX /*= 0*/, int32_t minRangeY /*= 0*/, int32_t maxRangeY /*= 0*/)
{
    if (centerPos.z >= MAP_MAX_LAYERS) {
        return;
    }

    bool foundCache = false;
    bool cacheResult = false;

    minRangeX = (minRangeX == 0 ? -maxViewportX : -minRangeX);
    maxRangeX = (maxRangeX == 0 ? maxViewportX : maxRangeX);
    minRangeY = (minRangeY == 0 ? -maxViewportY : -minRangeY);
    maxRangeY = (maxRangeY == 0 ? maxViewportY : maxRangeY);

    if (minRangeX == -maxViewportX && maxRangeX == maxViewportX && minRangeY == -maxViewportY && maxRangeY == maxViewportY && multifloor) {
        if (onlyPlayers) {
            auto it = playersSpectatorCache.find(centerPos);
            if (it != playersSpectatorCache.end()) {
                if (!spectators.empty()) {
                    spectators.addSpectators(it->second);
                } else {
                    spectators = it->second;
                }

                foundCache = true;
            }
        }

        if (!foundCache) {
            auto it = spectatorCache.find(centerPos);
            if (it != spectatorCache.end()) {
                if (!onlyPlayers) {
                    if (!spectators.empty()) {
                        const SpectatorVec& cachedSpectators = it->second;
                        spectators.addSpectators(cachedSpectators);
                    } else {
                        spectators = it->second;
                    }
                } else {
                    const SpectatorVec& cachedSpectators = it->second;
                    for (Creature* spectator : cachedSpectators) {
                        if (spectator->getPlayer()) {
                            spectators.emplace_back(spectator);
                        }
                    }
                }

                foundCache = true;
            } else {
                cacheResult = true;
            }
        }
    }

    if (!foundCache) {
        int32_t minRangeZ;
        int32_t maxRangeZ;

        if (multifloor) {
            if (centerPos.z > 7) {
                //underground (8->15)
                minRangeZ = std::max<int32_t>(centerPos.getZ() - 2, 0);
                maxRangeZ = std::min<int32_t>(centerPos.getZ() + 2, MAP_MAX_LAYERS - 1);
            } else if (centerPos.z == 6) {
                minRangeZ = 0;
                maxRangeZ = 8;
            } else if (centerPos.z == 7) {
                minRangeZ = 0;
                maxRangeZ = 9;
            } else {
                minRangeZ = 0;
                maxRangeZ = 7;
            }
        } else {
            minRangeZ = centerPos.z;
            maxRangeZ = centerPos.z;
        }

        getSpectatorsInternal(spectators, centerPos, minRangeX, maxRangeX, minRangeY, maxRangeY, minRangeZ, maxRangeZ, onlyPlayers);

        if (cacheResult) {
            if (onlyPlayers) {
                playersSpectatorCache[centerPos] = spectators;
            } else {
                spectatorCache[centerPos] = spectators;
            }
        }
    }
}

can it be in here there is some problems? maybe a scripter can look through it and say if it's ok, maybe compare with something that works?
 
Last edited:
Back
Top