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

TFS 0.X TFS 0.4 Display player rebirth instead of level on the chat.

Aurolio

New Member
Joined
Aug 26, 2018
Messages
45
Reaction score
3
I've recently changed the source of my TFS 0.4 so that the number of Rebirths is displayed instead of level in the skills tab. What I want to do now is make it display the rebirth on the chat (instead of level). I managed to do it, but it crashes the server whenever I talk to an NPC.

Here is the source code for the skills tab (Rebirth instead of Level):

Code:
void ProtocolGame::AddPlayerStats(NetworkMessage_ptr msg)
{
    msg->put<char>(0xA0);
    if (player->getPlayerInfo(PLAYERINFO_MAXHEALTH) > 0)
    {
        msg->put<uint16_t>(uint16_t(player->getHealth() * 100 / player->getPlayerInfo(PLAYERINFO_MAXHEALTH)));
        msg->put<uint16_t>(100);
    }
    else
    {
        msg->put<uint16_t>(0);
        msg->put<uint16_t>(0);
    }
    msg->put<uint32_t>(uint32_t(player->getFreeCapacity() * 100));
   
    uint64_t experience = player->getLevel();
    if(experience > 0x7FFFFFFF) // client debugs after 2,147,483,647 exp
        msg->put<uint32_t>(0x7FFFFFFF);
    else
        msg->put<uint32_t>(experience);
           
    std::string rebirths;
    player->getStorage(85987, rebirths);
    msg->put<uint16_t>(std::max(0, atoi(rebirths.c_str())));
    msg->put<char>(player->getPlayerInfo(PLAYERINFO_LEVELPERCENT));
    if (player->getPlayerInfo(PLAYERINFO_MAXMANA) > 0)
    {
        msg->put<uint16_t>(player->getPlayerInfo(PLAYERINFO_MANA) * 100 / player->getPlayerInfo(PLAYERINFO_MAXMANA));
        msg->put<uint16_t>(100);
    }
    else
    {
        msg->put<uint16_t>(0);
        msg->put<uint16_t>(0);
    }
    msg->put<char>(player->getPlayerInfo(PLAYERINFO_MAGICLEVEL));
    msg->put<char>(player->getPlayerInfo(PLAYERINFO_MAGICLEVELPERCENT));
    msg->put<char>(player->getPlayerInfo(PLAYERINFO_SOUL));
    msg->put<uint16_t>(player->getStaminaMinutes());
}

It works perfectly fine.

Now here is the code that crashes the server whenever I talk to an npc:

Code:
oid ProtocolGame::AddCreatureSpeak(NetworkMessage_ptr msg, const Creature* creature, SpeakClasses type,
    std::string text, uint16_t channelId, uint32_t time/*= 0*/, Position* pos/* = NULL*/, ProtocolGame* pg)
{
    msg->put<char>(0xAA);
    if(creature)
    {
        const Player* speaker = creature->getPlayer();
        if(speaker)
        {
            msg->put<uint32_t>(++g_chat.statement);
            g_chat.statementMap[g_chat.statement] = text;
        }
        else
            msg->put<uint32_t>(0x00);

        if(creature->getSpeakType() != SPEAK_CLASS_NONE)
            type = creature->getSpeakType();

        std::string pname;
        if(speaker && pg != NULL && pg->isCast)
            pname = pg->viewerName;
        else
            pname = creature->getName();

        switch(type)
        {
            case SPEAK_CHANNEL_RA:
                msg->putString("");
                break;
            case SPEAK_RVR_ANSWER:
                msg->putString("Gamemaster");
                break;
            default:
                msg->putString(!creature->getHideName() ? pname: "");
                break;
        }
        std::string rebirths;
        speaker->getStorage(85987, rebirths);
       
        if(speaker && type != SPEAK_RVR_ANSWER && !speaker->isAccountManager() && !speaker->hasCustomFlag(PlayerCustomFlag_HideLevel) && (pg == NULL || pg != NULL && !pg->getIsCast()))
                msg->put<uint16_t>(std::max(0, atoi(rebirths.c_str())));
        else
            msg->put<uint16_t>(0x00);

    }
    else
    {
        msg->put<uint32_t>(0x00);
        msg->putString("");
        msg->put<uint16_t>(0x00);
    }

    msg->put<char>(type);
    switch(type)
    {
        case SPEAK_SAY:
        case SPEAK_WHISPER:
        case SPEAK_YELL:
        case SPEAK_MONSTER_SAY:
        case SPEAK_MONSTER_YELL:
        case SPEAK_PRIVATE_NP:
        {
            if(pos)
                msg->putPosition(*pos);
            else if(creature)
                msg->putPosition(creature->getPosition());
            else
                msg->putPosition(Position(0,0,7));

            break;
        }

        case SPEAK_CHANNEL_Y:
        case SPEAK_CHANNEL_RN:
        case SPEAK_CHANNEL_RA:
        case SPEAK_CHANNEL_O:
        case SPEAK_CHANNEL_W:
            msg->put<uint16_t>(channelId);
            break;

        case SPEAK_RVR_CHANNEL:
        {
            msg->put<uint32_t>(uint32_t(OTSYS_TIME() / 1000 & 0xFFFFFFFF) - time);
            break;
        }

        default:
            break;
    }

    msg->putString(text);
}

If I am not talking to NPC everything works fine, I can see other players rebirths. The problem is when I talk to NPC.
 
Last edited:
Solution
My guess is you're de-referencing a null pointer (speaker) on line 38 (speaker->getStorage(85987, rebirths)). This would be better:
C++:
if (speaker && type != SPEAK_RVR_ANSWER && !speaker->isAccountManager() && !speaker->hasCustomFlag(PlayerCustomFlag_HideLevel) && (pg == NULL || !pg->getIsCast())) {
    std::string rebirths;
    speaker->getStorage(85987, rebirths);
    msg->put<uint16_t>(std::max(0, atoi(rebirths.c_str())));
} else {
    msg->put<uint16_t>(0x00);
}
Whenever you de-reference a pointer (by using ->) you must ensure it's a valid pointer, otherwise it will segfault and your server will crash.
Because an npc doesn't have rebirths I quess? so maybe put inside the code a if to check if its a npc or not?

If its an npc just return level?
 
My guess is you're de-referencing a null pointer (speaker) on line 38 (speaker->getStorage(85987, rebirths)). This would be better:
C++:
if (speaker && type != SPEAK_RVR_ANSWER && !speaker->isAccountManager() && !speaker->hasCustomFlag(PlayerCustomFlag_HideLevel) && (pg == NULL || !pg->getIsCast())) {
    std::string rebirths;
    speaker->getStorage(85987, rebirths);
    msg->put<uint16_t>(std::max(0, atoi(rebirths.c_str())));
} else {
    msg->put<uint16_t>(0x00);
}
Whenever you de-reference a pointer (by using ->) you must ensure it's a valid pointer, otherwise it will segfault and your server will crash.
 
Solution
Can someone help me? I use other version :/

Thanks :)

Lua:
void ProtocolGame::AddPlayerStats(OutputMessage_ptr msg)
{
    msg->addByte(0xA0);
if (player->getPlayerInfo(PLAYERINFO_MAXHEALTH) > 0)
    {
        float f_h_percent = (float) player->getHealth()  / player->getPlayerInfo(PLAYERINFO_MAXHEALTH);
        uint16_t h_percent = f_h_percent * 100;
        msg->add<uint16_t>(h_percent);
        msg->add<uint16_t>(100);
    }
    else
    {
        msg->add<uint16_t>(0);
        msg->add<uint16_t>(0); 
    }
    
    msg->add<uint32_t>(uint32_t(player->getFreeCapacity() * 100));
    uint64_t experience = player->getExperience();
    
    if(experience > 0x7FFFFFFF)
        msg->add<uint32_t>(0x0);
    else
        msg->add<uint32_t>(experience);

    msg->add<uint16_t>(player->getPlayerInfo(PLAYERINFO_LEVEL));
    msg->addByte(player->getPlayerInfo(PLAYERINFO_LEVELPERCENT));
    
    if (player->getPlayerInfo(PLAYERINFO_MAXMANA) > 0)
    {   
        float f_m_percent = (float) player->getPlayerInfo(PLAYERINFO_MANA) /  (float) player->getPlayerInfo(PLAYERINFO_MAXMANA);
        uint16_t m_percent = f_m_percent * 100;
        msg->add<uint16_t>(m_percent);
        msg->add<uint16_t>(100);
    }
    else
    {
        msg->add<uint16_t>(0);
        msg->add<uint16_t>(0);
    }
    msg->addByte(player->getPlayerInfo(PLAYERINFO_MAGICLEVEL));
    msg->addByte(player->getPlayerInfo(PLAYERINFO_MAGICLEVELPERCENT));
    msg->addByte(player->getPlayerInfo(PLAYERINFO_SOUL));
    msg->add<uint16_t>(player->getStaminaMinutes());
}
 
Back
Top