• 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 Otcv8 floor view (tfs 1.5 8.60 Nekiro)

GresQu

New Member
Joined
Apr 2, 2021
Messages
4
Reaction score
0
Hi
TFS 1.5 downgrades 8.60
Otclient v8 - GitHub - OTCv8/otcv8-dev: OTCv8 Development repository (source code) (https://github.com/OTCv8/otcv8-dev)
I have problem with floor view when im on floor 9+ everything work fine but when i restart client and login on floor -8(8,7,6,5,4,3,2,1,0) then i see black tiles relog doesn't help,but when i going out off screen and back then all back to normal until reset the client.
i follow this two threads

screens : that black tiles are on floor 8/7/6/5/4/3/2/1/0
Gyazo (https://gyazo.com/2f76ac3319f6bf4d9dfd23a614c033ed) - 6 floor
Gyazo (https://gyazo.com/f82b30455206680a18d1d5f6fb21b1d6) - 6 floor after visit 9/10/11/12 floors
Gyazo (https://gyazo.com/ad5665fcc9465f39cd4587a19995bd41) - 8 floor
Gyazo (https://gyazo.com/520a189d115fd23ec1cb9fb78e2678d9) - 8 floor after visit 9/10/11/12 floors
i think below its all what i edit for this floor view i want to see from floor 0 to 15 and 15 to 0 if available
tell me when you need other code or just full files.
Protocolgame.cpp (server side)
C++:
void ProtocolGame::GetMapDescription(int32_t x, int32_t y, int32_t z, int32_t width, int32_t height, NetworkMessage& msg)
{
    int32_t skip = -1;
    int32_t startz, endz, zstep = 0;

    if (z > 7) {
        startz = z - 8;
        endz = std::min<int32_t>(MAP_MAX_LAYERS - 1, z + 8);
        zstep = 1;
    } else {
        startz = 15;
        endz = 0;
        zstep = -1;
    }

    for (int32_t nz = startz; nz != endz + zstep; nz += zstep) {
        GetFloorDescription(msg, x, y, nz, width, height, z - nz, skip);
    }

    if (skip >= 0) {
        msg.addByte(skip);
        msg.addByte(0xFF);
    }
}

bool ProtocolGame::canSee(int32_t x, int32_t y, int32_t z) const
{
    if (!player) {
        return false;
    }

    const Position& myPos = player->getPosition();
    if (myPos.z <= 7) {
        //we are on ground level or above (7 -> 0)
        //view is from 7 -> 0
        if (z > 15) {
            return false;
        }
    }
    else {
        if (myPos.z >= 8) {
            //we are underground (8 -> 15)
            //view is +/- 2 from the floor we stand on
            if (std::abs(myPos.getZ() - z) > 8) {
                return false;
            }
        }
    }

Client
Protocolgameparse.cpp
C++:
void ProtocolGame::setMapDescription(const InputMessagePtr& msg, int x, int y, int z, int width, int height)
{
    int startz, endz, zstep;

    if (z > Otc::SEA_FLOOR) {
        startz = z - Otc::AWARE_UNDEGROUND_FLOOR_RANGE;
        endz = std::min<int>(z + Otc::AWARE_UNDEGROUND_FLOOR_RANGE, (int)Otc::MAX_Z);
        zstep = 1;
    } else {
        startz = Otc::SEA_FLOOR+8;
        endz = 0;
        zstep = -1;
    }

    int skip = 0;
    for (int nz = startz; nz != endz + zstep; nz += zstep)
        skip = setFloorDescription(msg, x, y, nz, width, height, z - nz, skip);
}

map.cpp
Code:
int Map::getFirstAwareFloor()
{
    if(m_centralPosition.z > Otc::SEA_FLOOR)
        return m_centralPosition.z-Otc::AWARE_UNDEGROUND_FLOOR_RANGE;
    else
        return 0;
}

int Map::getLastAwareFloor()
{
    if(m_centralPosition.z > Otc::SEA_FLOOR)
        return std::min<int>(m_centralPosition.z+Otc::AWARE_UNDEGROUND_FLOOR_RANGE, (int)Otc::MAX_Z);
    else
        return Otc::SEA_FLOOR+8;
}

mapview.cpp
C++:
int MapView::calcLastVisibleFloor()
{
    if(!m_multifloor)
        return calcFirstVisibleFloor();

    int z = 7;

    Position cameraPosition = getCameraPosition();
    // this could happens if the player is not known yet
    if(cameraPosition.isValid()) {
        // view only underground floors when below sea level
        if(cameraPosition.z > Otc::SEA_FLOOR)
            z = cameraPosition.z + Otc::AWARE_UNDEGROUND_FLOOR_RANGE;
        else
            z = 15;
    }

    if(m_lockedFirstVisibleFloor != -1)
        z = std::max<int>(m_lockedFirstVisibleFloor, z);

    // just ensure the that the floor is in the valid range
    z = stdext::clamp<int>(z, 0, (int)Otc::MAX_Z);
    return z;
}

int MapView::calcFirstVisibleFloor(bool forFading)
{
    int z = 7;
    // return forced first visible floor
    if(m_lockedFirstVisibleFloor != -1) {
        z = m_lockedFirstVisibleFloor;
    } else {
        Position cameraPosition = getCameraPosition();

        // this could happens if the player is not known yet
        if(cameraPosition.isValid()) {
            // avoid rendering multifloors in far views
            if(!m_multifloor) {
                z = cameraPosition.z;
            } else {
                // if nothing is limiting the view, the first visible floor is 0
                int firstFloor = 0;

                // limits to underground floors while under sea level
                if (cameraPosition.z > Otc::SEA_FLOOR)
                    firstFloor = 0;

                // loop in 3x3 tiles around the camera
                for(int ix = -1; ix <= 1 && firstFloor < cameraPosition.z && !forFading; ++ix) {
                    for(int iy = -1; iy <= 1 && firstFloor < cameraPosition.z; ++iy) {
                        Position pos = cameraPosition.translated(ix, iy);

                        // process tiles that we can look through, e.g. windows, doors
                        if((ix == 0 && iy == 0) || ((std::abs(ix) != std::abs(iy)) && g_map.isLookPossible(pos))) {
                            Position upperPos = pos;
                            Position coveredPos = pos;

                            while(coveredPos.coveredUp() && upperPos.up() && upperPos.z >= firstFloor) {
                                // check tiles physically above
                                TilePtr tile = g_map.getTile(upperPos);
                                if(tile && tile->limitsFloorsView(!g_map.isLookPossible(pos))) {
                                    firstFloor = upperPos.z + 1;
                                    break;
                                }

                                // check tiles geometrically above
                                tile = g_map.getTile(coveredPos);
                                if(tile && tile->limitsFloorsView(g_map.isLookPossible(pos))) {
                                    firstFloor = coveredPos.z + 1;
                                    break;
                                }
                            }
                        }
                    }
                }
                z = firstFloor;
            }
        }
    }

    // just ensure the that the floor is in the valid range
    z = stdext::clamp<int>(z, 0, (int)Otc::MAX_Z);
    return z;
}

int MapView::calcLastVisibleFloor()
{
    if(!m_multifloor)
        return calcFirstVisibleFloor();

    int z = 7;

    Position cameraPosition = getCameraPosition();
    // this could happens if the player is not known yet
    if(cameraPosition.isValid()) {
        // view only underground floors when below sea level
        if(cameraPosition.z > Otc::SEA_FLOOR)
            z = cameraPosition.z + Otc::AWARE_UNDEGROUND_FLOOR_RANGE;
        else
            z = 15;
    }

    if(m_lockedFirstVisibleFloor != -1)
        z = std::max<int>(m_lockedFirstVisibleFloor, z);

    // just ensure the that the floor is in the valid range
    z = stdext::clamp<int>(z, 0, (int)Otc::MAX_Z);
    return z;
}

const.h

C++:
{
    enum : int {
        MAX_ELEVATION = 24,

        SEA_FLOOR = 7,
        MAX_Z = 15,
        UNDERGROUND_FLOOR = SEA_FLOOR+1,
        AWARE_UNDEGROUND_FLOOR_RANGE = 8,

        INVISIBLE_TICKS_PER_FRAME = 500,
        INVISIBLE_TICKS_PER_FRAME_FAST = 100,
        ITEM_TICKS_PER_FRAME = 500,
        ITEM_TICKS_PER_FRAME_FAST = 100,
        ANIMATED_TEXT_DURATION = 1000,
        STATIC_DURATION_PER_CHARACTER = 60,
        MIN_STATIC_TEXT_DURATION = 3000,
        MAX_STATIC_TEXT_WIDTH = 200,
        MAX_AUTOWALK_STEPS_RETRY = 10,
        MAX_AUTOWALK_DIST = 127
    };
 
Last edited:
ref

i try undo changes in const.h with AWARE_UNDEGROUND_FLOOR_RANGE and make this that same way as sea_floor

so i change this 3 files mapview.cpp/map.cpp/protocolgameparse.cpp AWARE_UNDEGROUND_FLOOR_RANGE +/- 4

but i get more view errors probably i do something wrong with edit.

i change also value in MapView::calcFirstVisibleFloor / MapView::calcLastVisibleFloor() but that doesn't help too.

i undo all changes and back to the state from the first post

I have no idea how to fix that view. Build Client take me about 15 min so i cant do fast changes to try,try,try because im waste a lot of time.
probably I will do more tests on the weekend.


Client protocolgameparse.cpp



C++:
void ProtocolGame::setMapDescription(const InputMessagePtr& msg, int x, int y, int z, int width, int height)

{

    int startz, endz, zstep;



    if (z > Otc::SEA_FLOOR) {

        startz = z - Otc::AWARE_UNDEGROUND_FLOOR_RANGE - 4;

        endz = std::min<int>(z + Otc::AWARE_UNDEGROUND_FLOOR_RANGE + 4, (int)Otc::MAX_Z);

        zstep = 1;

    } else {

        startz = Otc::SEA_FLOOR + 4;

        endz = 0;

        zstep = -1;

    }



    int skip = 0;

    for (int nz = startz; nz != endz + zstep; nz += zstep)

        skip = setFloorDescription(msg, x, y, nz, width, height, z - nz, skip);

}



map.cpp

Code:
int Map::getFirstAwareFloor()
{
    if(m_centralPosition.z > Otc::SEA_FLOOR)
        return m_centralPosition.z-Otc::AWARE_UNDEGROUND_FLOOR_RANGE - 4;
    else
        return 0;
}

}

Code:
int Map::getLastAwareFloor()
{
    if(m_centralPosition.z > Otc::SEA_FLOOR)
        return std::min<int>(m_centralPosition.z+Otc::AWARE_UNDEGROUND_FLOOR_RANGE + 4, (int)Otc::MAX_Z);
    else
        return Otc::SEA_FLOOR+2;
}



const.h

Code:
    enum : int {

        MAX_ELEVATION = 24,



        SEA_FLOOR = 7,

        MAX_Z = 15,

        UNDERGROUND_FLOOR = SEA_FLOOR + 1,

        AWARE_UNDEGROUND_FLOOR_RANGE = 2,



        INVISIBLE_TICKS_PER_FRAME = 500,

        INVISIBLE_TICKS_PER_FRAME_FAST = 100,

        ITEM_TICKS_PER_FRAME = 500,

        ITEM_TICKS_PER_FRAME_FAST = 100,

        ANIMATED_TEXT_DURATION = 1000,

        STATIC_DURATION_PER_CHARACTER = 60,

        MIN_STATIC_TEXT_DURATION = 3000,

        MAX_STATIC_TEXT_WIDTH = 200,

        MAX_AUTOWALK_STEPS_RETRY = 10,

        MAX_AUTOWALK_DIST = 127

    };



mapview.cpp

C++:
int MapView::calcFirstVisibleFloor(bool forFading)

{

    int z = 7;

    // return forced first visible floor

    if (m_lockedFirstVisibleFloor != -1) {

        z = m_lockedFirstVisibleFloor;

    }

    else {

        Position cameraPosition = getCameraPosition();



        // this could happens if the player is not known yet

        if (cameraPosition.isValid()) {

            // avoid rendering multifloors in far views

            if (!m_multifloor) {

                z = cameraPosition.z;

            }

            else {

                // if nothing is limiting the view, the first visible floor is 0

                int firstFloor = 0;



                // limits to underground floors while under sea level

                if (cameraPosition.z > Otc::SEA_FLOOR)

                    firstFloor = std::max<int>(cameraPosition.z - Otc::AWARE_UNDEGROUND_FLOOR_RANGE - 4, (int)Otc::UNDERGROUND_FLOOR);



                // loop in 3x3 tiles around the camera

                for (int ix = -1; ix <= 1 && firstFloor < cameraPosition.z && !forFading; ++ix) {

                    for (int iy = -1; iy <= 1 && firstFloor < cameraPosition.z; ++iy) {

                        Position pos = cameraPosition.translated(ix, iy);



                        // process tiles that we can look through, e.g. windows, doors

                        if ((ix == 0 && iy == 0) || ((std::abs(ix) != std::abs(iy)) && g_map.isLookPossible(pos))) {

                            Position upperPos = pos;

                            Position coveredPos = pos;



                            while (coveredPos.coveredUp() && upperPos.up() && upperPos.z >= firstFloor) {

                                // check tiles physically above

                                TilePtr tile = g_map.getTile(upperPos);

                                if (tile && tile->limitsFloorsView(!g_map.isLookPossible(pos))) {

                                    firstFloor = upperPos.z + 1;

                                    break;

                                }



                                // check tiles geometrically above

                                tile = g_map.getTile(coveredPos);

                                if (tile && tile->limitsFloorsView(g_map.isLookPossible(pos))) {

                                    firstFloor = coveredPos.z + 1;

                                    break;

                                }

                            }

                        }

                    }

                }

                z = firstFloor;

            }

        }

    }



    // just ensure the that the floor is in the valid range

    z = stdext::clamp<int>(z, 0, (int)Otc::MAX_Z);

    return z;

}



int MapView::calcLastVisibleFloor()

{

    if (!m_multifloor)

        return calcFirstVisibleFloor();



    int z = 7;



    Position cameraPosition = getCameraPosition();

    // this could happens if the player is not known yet

    if (cameraPosition.isValid()) {

        // view only underground floors when below sea level

        if (cameraPosition.z > Otc::SEA_FLOOR)

            z = cameraPosition.z + Otc::AWARE_UNDEGROUND_FLOOR_RANGE - 4;

        else

            z = Otc::SEA_FLOOR + 4;

    }



    if (m_lockedFirstVisibleFloor != -1)

        z = std::max<int>(m_lockedFirstVisibleFloor, z);



    // just ensure the that the floor is in the valid range

    z = stdext::clamp<int>(z, 0, (int)Otc::MAX_Z);

    return z;

}



Server SIDE protocolgame.cpp



C++:
void ProtocolGame::GetMapDescription(int32_t x, int32_t y, int32_t z, int32_t width, int32_t height, NetworkMessage& msg)

{

    int32_t skip = -1;

    int32_t startz, endz, zstep = 0;



    if (z > 7) {

        startz = z - 6;

        endz = std::min<int32_t>(MAP_MAX_LAYERS - 1, z + 6);

        zstep = 1;

    } else {

        startz = 11;

        endz = 0;

        zstep = -1;

    }



    for (int32_t nz = startz; nz != endz + zstep; nz += zstep)

        GetFloorDescription(msg, x, y, nz, width, height, z - nz, skip);



    if (skip >= 0)

    {

        msg.addByte(skip);

        msg.addByte(0xFF);

        //cc += skip;

    }

}



bool ProtocolGame::canSee(int32_t x, int32_t y, int32_t z) const

{

    if (!player) {

        return false;

    }



    const Position& myPos = player->getPosition();

    if (myPos.z <= 7) {

        //we are on ground level or above (7 -> 0)

        //view is from 7 -> 0

        if (z > 11) {

            return false;

        }

    }

    else {

        if (myPos.z >= 8) {

            //we are underground (8 -> 15)

            //view is +/- 2 from the floor we stand on

            if (std::abs(myPos.getZ() - z) > 6) {

                return false;

            }

        }

    }



    //negative offset means that the action taken place is on a lower floor than ourself

    int32_t offsetz = myPos.getZ() - z;

    if ((x >= myPos.getX() - Map::maxClientViewportX + offsetz) && (x <= myPos.getX() + (Map::maxClientViewportX + 1) + offsetz) &&

        (y >= myPos.getY() - Map::maxClientViewportY + offsetz) && (y <= myPos.getY() + (Map::maxClientViewportY + 1) + offsetz)) {

        return true;

    }

    return false;

}
 
ref
i try few value changes in this files mapview.cpp/map.cpp/protocolgameparse.cpp but that doesn't help.
i have no idea how to fix that any suggestion will be helpful.
 
I'm sort of confused guys, I went through the trouble of compiling fresh otcv8 and nekiro 1.5 TFS with my downgrade and I'm a little unsure as to what the problem is?

Also tried it by forcefully by shutting down the client and logging in again, am I misinterpreting how to trigger the bug?
 

Attachments

It occurs when logging in on floor 7, however, after moving to the floors below it becomes normal
Post automatically merged:

when log in floor 7:


1.png


after walk in the floor 15 and back to floor 7 OR walk off screen and then return to the screen where the floors below are


2.png
Post automatically merged:

The problem is when you log in on a floor that has several floors below floor 7.

Apparently the problem is when logging in, because when you walk away from the screen and then walk back in it recognizes the floors below...
 
Last edited:
I'm trying to find something related to the function onCreatureApper, because it only happens when the player enters the client, but I haven't made any progress yet.
@Dries390 Did you manage to run the bug ?
 
ot2.gif

I haven't actually; tried logging in on z = 7 and this was the result. Even tried adding the changes to const.h (not sure why, my source code does not contain them). Working with a fresh Nekiro 1.5 TFS downgrade and fresh otcv8 client with my changes (and only my changes) included and everything seems to work like I'd expect.

Well, I plugged in some of your code snippets v.s. mine in a text comparison tool. The code in the first post doesn't match up with mine? Is that possible?

Take the first modification for the client for example (void ProtocolGame::GetMapDescription(int32_t x, int32_t y, int32_t z, int32_t width, int32_t height, NetworkMessage& msg))

codeCompare.PNG
 
Everything is fine on the tfs side, as I tested it on OTC Edubart and it works correctly, that is, the problem is with otcv8, but oddly enough it's working for you!

I'll review the codes again to see if I forgot anything, but I find it difficult as I've already reviewed them twice
Post automatically merged:

I've already reviewed it again and I don't know what could be happening, could you link the files protocolgameparse.cpp, map.cpp and mapview.cpp from the client please?
 
Last edited:
I've already checked and everything is actually correct on the client's side, do you think it could be due to tfs? I use TFS 1.3 itself linked to otcv8:
I was discarding this option because the configurations of tfs 1.5 and tfs 1.3 are identical when related to the changes you made
But thinking on the other hand, this tfs optimizes several things to be better compatible with otcv8, so that could be it, you can test it with it to see if that's the case?
 
ot3.gif


I run TFS 1.3 myself, I actually logged in to both servers (1.3 && 1.5) with this otcv8 and they both seemed to work just fine.

Edit: Taking a look now.
 
Last edited:
But was it with tfs 1.3?

This tfs was modified by Kondra to be more compatible with otcv8
Post automatically merged:

Seeing what you did there now, I think I expressed myself badly about the bug, it doesn't occur when you relog, but rather when you close the client and open it again
Post automatically merged:

Att: I just tested it with the Nekiro 1.5 downgrade and it worked perfectly, so it's something related to the TFS source!

but it is specifically with this otcv8 source!
Post automatically merged:

@Dries390 I found the error BRO !
it was specifically related to this tfs that I'm using
in protocolgame.cpp find void ProtocolGame::sendMapDescription(const Position& pos):
As I said, tfs optimizes as much as possible for otcv8, and in this function: void ProtocolGame::sendMapDescription(const Position& pos)

it takes into account whether you are using otcv8 or not, so just follow the second step of your tutorial and apply it to this function too!
 
Last edited:
But was it with tfs 1.3?

This tfs was modified by Kondra to be more compatible with otcv8
Post automatically merged:

Seeing what you did there now, I think I expressed myself badly about the bug, it doesn't occur when you relog, but rather when you close the client and open it again
Post automatically merged:

Att: I just tested it with the Nekiro 1.5 downgrade and it worked perfectly, so it's something related to the TFS source!

but it is specifically with this otcv8 source!
Post automatically merged:

@Dries390 I found the error BRO !
it was specifically related to this tfs that I'm using
in protocolgame.cpp find void ProtocolGame::sendMapDescription(const Position& pos):
As I said, tfs optimizes as much as possible for otcv8, and in this function: void ProtocolGame::sendMapDescription(const Position& pos)

it takes into account whether you are using otcv8 or not, so just follow the second step of your tutorial and apply it to this function too!
So you're good? I just fumbled that particular engine online, was about to start testing once I found out what a token was xD
 
HAHAHAHA I also don't know what this token is for, I removed it from my home screenIt is not necessary to fill it out


Yes, everything is fine now, at least for now, I will carry out more tests throughout the week and if I find a bug I will return here

thank you very much BRO
 
@GresQu
But was it with tfs 1.3?

This tfs was modified by Kondra to be more compatible with otcv8
Post automatically merged:

Seeing what you did there now, I think I expressed myself badly about the bug, it doesn't occur when you relog, but rather when you close the client and open it again
Post automatically merged:

Att: I just tested it with the Nekiro 1.5 downgrade and it worked perfectly, so it's something related to the TFS source!

but it is specifically with this otcv8 source!
Post automatically merged:

@Dries390 I found the error BRO !
it was specifically related to this tfs that I'm using
in protocolgame.cpp find void ProtocolGame::sendMapDescription(const Position& pos):
As I said, tfs optimizes as much as possible for otcv8, and in this function: void ProtocolGame::sendMapDescription(const Position& pos)

it takes into account whether you are using otcv8 or not, so just follow the second step of your tutorial and apply it to this function too!

so you can apply my pure code then just change what @Menoxcidee said here, if you're using TFS-otcv8. If you're using Nekiro it should be fine, otherwise contact me.

No problem @Menoxcidee, just really glad you got it working!
 
Back
Top