• 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:
@GresQu


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!

I couldn't have done it without your help, after all I was convinced that the problem was with the client

But from now on I will always remember that this tfs-otcv8 base is different when it is combined with client-otcv8
 
so hwo did you solve the problem?
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!


"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!"
 
"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!"
I added it for TFS 1.4.2, with otcv8 modifications. After i edited the sendMap() it worked, however, i'm having issues seeing monsters/players on deeper floors.
 
I added it for TFS 1.4.2, with otcv8 modifications. After i edited the sendMap() it worked, however, i'm having issues seeing monsters/players on deeper floors.
I'll try and setup a server again later and see if I can iron out all of the kinks!
Post automatically merged:

I added it for TFS 1.4.2, with otcv8 modifications. After i edited the sendMap() it worked, however, i'm having issues seeing monsters/players on deeper floors.
Could you perhaps be as specific as possible? What do you mean by "seeing" and "deeper floors"?
 
Last edited:
@Dries390 Hi bro, I did more tests and noticed some errors, remembering that I am using:

TFS 1.3 based on OTCV8: GitHub - OTCv8/forgottenserver: A free and open-source MMORPG server emulator written in C++, compatible with OTClientV8 (https://github.com/OTCv8/forgottenserver)

OTCLIENT V8: GitHub - OTCv8/otcv8-dev: OTCv8 Development repository (source code) (https://github.com/OTCv8/otcv8-dev)

When the player goes up to floor 5 or lower, the monsters stop moving, and after that when the player returns to floor 6 or higher it returns these errors:

Sem título.png

Post automatically merged:

ATT: I did more tests and apparently what is happening is the following, when player.z <= 5 he does not receive information from the creatures that are at z > 7. Soon, the creatures start to move but the player is not receiving this information, and when he goes down the floors he starts to receive this error because the creatures are no longer in the same place as when he went to z <= 5.
Post automatically merged:

ATT: I think a modification is needed in the "void ProtocolGame::sendMoveCreature" function or in function to view creatures on the floors below
Post automatically merged:

I managed to solve it guys, now there are no more errors and when the creatures move, they are updated for the player. The solution is as follows, in the TFS map.cpp file look for the void function "Map::getSpectators" and change it inside:

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;
}
}

for:

if (multifloor) {
minRangeZ = 0;
maxRangeZ = 15;
}



However, if there is only the player on the screen and no other player on the floors below, the creatures do not move because they are not receiving information that there is a player up there. I'm looking for where to change so that the creatures recognize that there is a player on the upper floors so they can move, if anyone knows it would be of great help.

NOTE: Probably solving this second problem automatically solves the first without having to make the modification I mentioned, but as I haven't managed it yet, this serves as a temporary measure!

But the important thing is that the biggest problem has been solved!
 
Last edited:
Back
Top