• 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!
  • If you're using Gesior 2012 or MyAAC, please review this thread for information about a serious security vulnerability and a fix.

C++ TFS 1.5 7.72 How to send cancel message after choosing locked outfit

dewral

Banned User
Joined
Dec 4, 2019
Messages
303
Solutions
10
Reaction score
206
Hi guys!
Basicaly i wanted that server send cancel message after you choose outfit you don't own.
This part is responsible for displaying all of outfits.
Tfs 1.5 772

C++:
switch (player->getSex()) {
        case PLAYERSEX_FEMALE: {
            msg.add<uint16_t>(351);
            if (player->isPremium()) {
                msg.add<uint16_t>(365);
            } else {
                msg.add<uint16_t>(357);            
            }

            break;
        }

        case PLAYERSEX_MALE: {
            msg.add<uint16_t>(300);
            if (player->isPremium()) {
                msg.add<uint16_t>(316);
            } else {
                msg.add<uint16_t>(306);
            }

            break;
        }

        default: {
            msg.add<uint16_t>(300);
            msg.add<uint16_t>(351);
        }
    }

    writeToOutputBuffer(msg);
}

Could someone help?
 
Last edited:
Solution
You commented somewhere about this as i remember. There was a lot of code to uncomment to make it work right?
You'll break cip client if you do that, unless you dont use it then its fine to use new protocol outfit window and enable this setting in your otclient.
This could be configurable, to make it easier, but I didn't work on downgrades since some time and I don't know if I'll be.
OP
OP
dewral

dewral

Banned User
Joined
Dec 4, 2019
Messages
303
Solutions
10
Reaction score
206
Change also this one
C++:
void ProtocolGame::parseSetOutfit(NetworkMessage& msg)
{
    Outfit_t newOutfit;
    newOutfit.lookType = msg.get<uint16_t>();
    newOutfit.lookHead = msg.getByte();
    newOutfit.lookBody = msg.getByte();
    newOutfit.lookLegs = msg.getByte();
    newOutfit.lookFeet = msg.getByte();
    newOutfit.lookAddons = msg.getByte();
    //newOutfit.lookMount = msg.get<uint16_t>();
    addGameTask(&Game::playerChangeOutfit, player->getID(), newOutfit);
}

and protocolgame.cpp

C++:
void ProtocolGame::sendOutfitWindow()
{
    const auto& outfits = Outfits::getInstance().getOutfits(player->getSex());
    if (outfits.size() == 0) {
        return;
    }

    NetworkMessage msg;
    msg.addByte(0xC8);

    Outfit_t currentOutfit = player->getDefaultOutfit();
    if (currentOutfit.lookType == 0) {
        Outfit_t newOutfit;
        newOutfit.lookType = outfits.front().lookType;
        currentOutfit = newOutfit;
    }

    /*Mount* currentMount = g_game.mounts.getMountByID(player->getCurrentMount());
    if (currentMount) {
        currentOutfit.lookMount = currentMount->clientId;
    }*/

    AddOutfit(msg, currentOutfit);

    std::vector<ProtocolOutfit> protocolOutfits;
    if (player->isAccessPlayer()) {
        static const std::string gamemasterOutfitName = "Gamemaster";
        protocolOutfits.emplace_back(gamemasterOutfitName, 75, 0);
    }

    protocolOutfits.reserve(outfits.size());
    for (const Outfit& outfit : outfits) {
        uint8_t addons;
        if (!player->getOutfitAddons(outfit, addons)) {
            continue;
        }

        protocolOutfits.emplace_back(outfit.name, outfit.lookType, addons);
        if (protocolOutfits.size() == 50) { // Game client currently doesn't allow more than 50 outfits
            break;
        }
    }

    msg.addByte(protocolOutfits.size());
    for (const ProtocolOutfit& outfit : protocolOutfits) {
        msg.add<uint16_t>(outfit.lookType);
        msg.addString(outfit.name);
        msg.addByte(outfit.addons);
    }

    /*
    std::vector<const Mount*> mounts;
    for (const Mount& mount : g_game.mounts.getMounts()) {
        if (player->hasMount(&mount)) {
            mounts.push_back(&mount);
        }
    }

    msg.addByte(mounts.size());
    for (const Mount* mount : mounts) {
        msg.add<uint16_t>(mount->clientId);
        msg.addString(mount->name);
    }*/

    writeToOutputBuffer(msg);
}
 

jakub742

Member
Joined
May 1, 2010
Messages
110
Solutions
2
Reaction score
8
Location
Slovakia
Change also this one
C++:
void ProtocolGame::parseSetOutfit(NetworkMessage& msg)
{
    Outfit_t newOutfit;
    newOutfit.lookType = msg.get<uint16_t>();
    newOutfit.lookHead = msg.getByte();
    newOutfit.lookBody = msg.getByte();
    newOutfit.lookLegs = msg.getByte();
    newOutfit.lookFeet = msg.getByte();
    newOutfit.lookAddons = msg.getByte();
    //newOutfit.lookMount = msg.get<uint16_t>();
    addGameTask(&Game::playerChangeOutfit, player->getID(), newOutfit);
}

and protocolgame.cpp

C++:
void ProtocolGame::sendOutfitWindow()
{
    const auto& outfits = Outfits::getInstance().getOutfits(player->getSex());
    if (outfits.size() == 0) {
        return;
    }

    NetworkMessage msg;
    msg.addByte(0xC8);

    Outfit_t currentOutfit = player->getDefaultOutfit();
    if (currentOutfit.lookType == 0) {
        Outfit_t newOutfit;
        newOutfit.lookType = outfits.front().lookType;
        currentOutfit = newOutfit;
    }

    /*Mount* currentMount = g_game.mounts.getMountByID(player->getCurrentMount());
    if (currentMount) {
        currentOutfit.lookMount = currentMount->clientId;
    }*/

    AddOutfit(msg, currentOutfit);

    std::vector<ProtocolOutfit> protocolOutfits;
    if (player->isAccessPlayer()) {
        static const std::string gamemasterOutfitName = "Gamemaster";
        protocolOutfits.emplace_back(gamemasterOutfitName, 75, 0);
    }

    protocolOutfits.reserve(outfits.size());
    for (const Outfit& outfit : outfits) {
        uint8_t addons;
        if (!player->getOutfitAddons(outfit, addons)) {
            continue;
        }

        protocolOutfits.emplace_back(outfit.name, outfit.lookType, addons);
        if (protocolOutfits.size() == 50) { // Game client currently doesn't allow more than 50 outfits
            break;
        }
    }

    msg.addByte(protocolOutfits.size());
    for (const ProtocolOutfit& outfit : protocolOutfits) {
        msg.add<uint16_t>(outfit.lookType);
        msg.addString(outfit.name);
        msg.addByte(outfit.addons);
    }

    /*
    std::vector<const Mount*> mounts;
    for (const Mount& mount : g_game.mounts.getMounts()) {
        if (player->hasMount(&mount)) {
            mounts.push_back(&mount);
        }
    }

    msg.addByte(mounts.size());
    for (const Mount* mount : mounts) {
        msg.add<uint16_t>(mount->clientId);
        msg.addString(mount->name);
    }*/

    writeToOutputBuffer(msg);
}
parseSetOutfit() was already like that. Tried the sendOutfitWindow() but same glitching issue.
 

jakub742

Member
Joined
May 1, 2010
Messages
110
Solutions
2
Reaction score
8
Location
Slovakia
How did you register features?
Lua:
if(version >= 770) then
        g_game.enableFeature(GamePlayerAddons)
        g_game.enableFeature(GameLooktypeU16)
        g_game.enableFeature(GameMessageStatements)
        g_game.enableFeature(GameLoginPacketEncryption)
        g_game.enableFeature(GameNewOutfitProtocol)

    end
 
OP
OP
dewral

dewral

Banned User
Joined
Dec 4, 2019
Messages
303
Solutions
10
Reaction score
206

jakub742

Member
Joined
May 1, 2010
Messages
110
Solutions
2
Reaction score
8
Location
Slovakia
OP
OP
dewral

dewral

Banned User
Joined
Dec 4, 2019
Messages
303
Solutions
10
Reaction score
206
I did not at that time, but i tried it and i wasnt able to login after that, instantly connection error in client. i'll try to look into it more at the weekend.
Make a thread on support i'll help you, i remember i had this issue when i first time to install this :)
 
Top