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

C++ Monster Level&skull Crash tfs 1.5 860

abdala ragab

Veteran OT User
Joined
Aug 18, 2018
Messages
522
Solutions
14
Reaction score
388
Location
gamelaot.sytes.net
Hello, I tried to add this system and it works well, but it has one error
If you use command /addskill player,level server crash
if you have task or items give exp after use or take reward server crash
This is the system

skull
Feature - [TFS 1.3] Monster Levels (https://otland.net/threads/tfs-1-3-monster-levels.260470/page-6)
I hope someone can help me
Thanks in advance
If you need more details let me know, but I think I explained it well
 
Solution
the same Monsters now give very low experience levels
Looking at your addExperience function it seems like for some reason you don't have the following lines after calculating the bonus from monster levels.


C++:
    g_events->eventPlayerOnGainExperience(this, source, exp, rawExp);
    if (exp == 0) {
        return;
    }

I believe you may have deleted it by mistake, that's why you started getting the warning about rawExp not being referenced.

1715640077211.png
Weird, code looks alright, maybe the problem is in the addition to player.cpp.

Change
C++:
    const Monster* monster = source->getMonster();
    if (monster && monster->getLevel() > 0) {
        exp += (exp * 0.08) * monster->getLevel();
    }

To:

C++:
if (source != nullptr) {
    const Monster* monster = source->getMonster();
    if (monster != nullptr) {
        int monsterlevel = monster->getLevel();
        if (monsterlevel > 0) {
            exp += (exp * 0.08) * monsterlevel;
        }
    }
}

See if that fixes it.
 
Last edited:
crash wait i test your editaddv.png
Before the amendment
after \/
Lua:
1>C:\otc\src\player.cpp(1606,11): warning C4189: 'rawExp': local variable is initialized but not referenced
1>(compiling source file '/src/player.cpp')
Can this line be corrected?
And the compile was done
The problem was solved, thank you
Post automatically merged:

my player.cpp
 
Last edited:
crash wait i test your editView attachment 84632
Before the amendment
after \/
Lua:
1>C:\otc\src\player.cpp(1606,11): warning C4189: 'rawExp': local variable is initialized but not referenced
1>(compiling source file '/src/player.cpp')
Can this line be corrected?
And the compile was done
The problem was solved, thank you
Post automatically merged:

my player.cpp
Yeah should be simple to remove that warning.

If you can see in your function you have
C++:
uint64_t rawExp = exp
I would search for rawExp in source and see if its referenced anywhere else, but it's basically saying that you're not using it so simply removing that line should fix the warning.
 
Yeah should be simple to remove that warning.

If you can see in your function you have
C++:
uint64_t rawExp = exp
I would search for rawExp in source and see if its referenced anywhere else, but it's basically saying that you're not using it so simply removing that line should fix the warning.
Indeed, that warning was cancelled, the system was tested, and everything works fine. Thank you. I wish you success always
Post automatically merged:

if (source != nullptr) { const Monster* monster = source->getMonster(); if (monster != nullptr) { int level = monster->getLevel(); if (level > 0) { exp += (exp * 0.08) * level; } } }
The player gets very few experience levels now
 
Last edited:
Indeed, that warning was cancelled, the system was tested, and everything works fine. Thank you. I wish you success always
Post automatically merged:


The player gets very few experience levels now
You should probably post your whole void Player::addExperience(Creature* source, uint64_t exp, bool sendText/* = false*/) function, also not sure if you had a different multiplier instead of 0.08, could be many things.

I modified my post, maybe it could be that since we were using "level" to store monster level it could be overriding it in other parts of the function, I changed it to monsterlevel.
 
You should probably post your whole void Player::addExperience(Creature* source, uint64_t exp, bool sendText/* = false*/) function, also not sure if you had a different multiplier instead of 0.08, could be many things.

I modified my post, maybe it could be that since we were using "level" to store monster level it could be overriding it in other parts of the function, I changed it to monsterlevel.
C++:
void Player::addExperience(Creature* source, uint64_t exp, bool sendText/* = false*/)
{
    uint64_t currLevelExp = Player::getExpForLevel(level);
    uint64_t nextLevelExp = Player::getExpForLevel(level + 1);
    uint64_t rawExp = exp;
    if (currLevelExp >= nextLevelExp) {
        //player has reached max level
        levelPercent = 0;
        sendStats();
        return;
    }
    
    //g_events->eventPlayerOnGainExperience(this, source, exp, rawExp);
    //if (exp == 0) {
    //    return;
    //}

    if (source != nullptr) {
    const Monster* monster = source->getMonster();
    if (monster != nullptr) {
        int level = monster->getLevel();
        if (level > 0) {
            exp += (exp * 00.08) * level;
        }
    }
}

    experience += exp;

    if (sendText) {
        std::string expString = std::to_string(exp) + (exp != 1 ? " experience points." : " experience point.");

        TextMessage message(MESSAGE_STATUS_DEFAULT, "You gained " + expString);
        sendTextMessage(message);

        g_game.addAnimatedText(std::to_string(exp), position, TEXTCOLOR_WHITE);

        SpectatorVec spectators;
        g_game.map.getSpectators(spectators, position, false, true);
        spectators.erase(this);
        if (!spectators.empty()) {
            message.type = MESSAGE_STATUS_DEFAULT;
            message.text = getName() + " gained " + expString;
            for (Creature* spectator : spectators) {
                spectator->getPlayer()->sendTextMessage(message);
            }
        }
    }

    uint32_t prevLevel = level;
    while (experience >= nextLevelExp) {
        ++level;
        healthMax += vocation->getHPGain();
        health += vocation->getHPGain();
        manaMax += vocation->getManaGain();
        mana += vocation->getManaGain();
        capacity += vocation->getCapGain();

        currLevelExp = nextLevelExp;
        nextLevelExp = Player::getExpForLevel(level + 1);
        if (currLevelExp >= nextLevelExp) {
            //player has reached max level
            break;
        }
    }

    if (prevLevel != level) {
        health = getMaxHealth();
        mana = getMaxMana();

        updateBaseSpeed();
        setBaseSpeed(getBaseSpeed());

        g_game.changeSpeed(this, 0);
        g_game.addCreatureHealth(this);

        const uint32_t protectionLevel = static_cast<uint32_t>(g_config.getNumber(ConfigManager::PROTECTION_LEVEL));
        if (prevLevel < protectionLevel && level >= protectionLevel) {
            g_game.updateCreatureWalkthrough(this);
        }

        if (party) {
            party->updateSharedExperience();
        }

        g_creatureEvents->playerAdvance(this, SKILL_LEVEL, prevLevel, level);

        sendTextMessage(MESSAGE_EVENT_ADVANCE, fmt::format("You advanced from Level {:d} to Level {:d}.", prevLevel, level));
    }

    if (nextLevelExp > currLevelExp) {
        levelPercent = Player::getPercentLevel(experience - currLevelExp, nextLevelExp - currLevelExp);
    } else {
        levelPercent = 0;
    }
    sendStats();
}

void Player::removeExperience(uint64_t exp, bool sendText/* = false*/)
{
    if (experience == 0 || exp == 0) {
        return;
    }

    g_events->eventPlayerOnLoseExperience(this, exp);
    if (exp == 0) {
        return;
    }

    uint64_t lostExp = experience;
    experience = std::max<int64_t>(0, experience - exp);

    if (sendText) {
        lostExp -= experience;

        std::string expString = std::to_string(lostExp) + (lostExp != 1 ? " experience points." : " experience point.");

        TextMessage message(MESSAGE_STATUS_DEFAULT, "You lost " + expString);
        sendTextMessage(message);

        g_game.addAnimatedText(std::to_string(lostExp), position, TEXTCOLOR_RED);

        SpectatorVec spectators;
        g_game.map.getSpectators(spectators, position, false, true);
        spectators.erase(this);
        if (!spectators.empty()) {
            message.type = MESSAGE_STATUS_DEFAULT;
            message.text = getName() + " lost " + expString;
            for (Creature* spectator : spectators) {
                spectator->getPlayer()->sendTextMessage(message);
            }
        }
    }

    uint32_t oldLevel = level;
    uint64_t currLevelExp = Player::getExpForLevel(level);

    while (level > 1 && experience < currLevelExp) {
        --level;
        healthMax = std::max<int32_t>(0, healthMax - vocation->getHPGain());
        manaMax = std::max<int32_t>(0, manaMax - vocation->getManaGain());
        capacity = std::max<int32_t>(0, capacity - vocation->getCapGain());
        currLevelExp = Player::getExpForLevel(level);
    }

    if (oldLevel != level) {
        health = getMaxHealth();
        mana = getMaxMana();

        updateBaseSpeed();
        setBaseSpeed(getBaseSpeed());

        g_game.changeSpeed(this, 0);
        g_game.addCreatureHealth(this);

        const uint32_t protectionLevel = static_cast<uint32_t>(g_config.getNumber(ConfigManager::PROTECTION_LEVEL));
        if (oldLevel >= protectionLevel && level < protectionLevel) {
            g_game.updateCreatureWalkthrough(this);
        }

        if (party) {
            party->updateSharedExperience();
        }

        sendTextMessage(MESSAGE_EVENT_ADVANCE, fmt::format("You were downgraded from Level {:d} to Level {:d}.", oldLevel, level));
    }

    uint64_t nextLevelExp = Player::getExpForLevel(level + 1);
    if (nextLevelExp > currLevelExp) {
        levelPercent = Player::getPercentLevel(experience - currLevelExp, nextLevelExp - currLevelExp);
    } else {
        levelPercent = 0;
    }
    sendStats();
}

uint8_t Player::getPercentLevel(uint64_t count, uint64_t nextLevelCount)
{
    if (nextLevelCount == 0) {
        return 0;
    }

    uint8_t result = (count * 100) / nextLevelCount;
    if (result > 100) {
        return 0;
    }
    return result;
}

void Player::onBlockHit()
{
    if (shieldBlockCount > 0) {
        --shieldBlockCount;

        if (hasShield()) {
            addSkillAdvance(SKILL_SHIELD, 1);
        }
    }
}
player.cpp
 
C++:
void Player::addExperience(Creature* source, uint64_t exp, bool sendText/* = false*/)
{
    uint64_t currLevelExp = Player::getExpForLevel(level);
    uint64_t nextLevelExp = Player::getExpForLevel(level + 1);
    uint64_t rawExp = exp;
    if (currLevelExp >= nextLevelExp) {
        //player has reached max level
        levelPercent = 0;
        sendStats();
        return;
    }
   
    //g_events->eventPlayerOnGainExperience(this, source, exp, rawExp);
    //if (exp == 0) {
    //    return;
    //}

    if (source != nullptr) {
    const Monster* monster = source->getMonster();
    if (monster != nullptr) {
        int level = monster->getLevel();
        if (level > 0) {
            exp += (exp * 00.08) * level;
        }
    }
}

    experience += exp;

    if (sendText) {
        std::string expString = std::to_string(exp) + (exp != 1 ? " experience points." : " experience point.");

        TextMessage message(MESSAGE_STATUS_DEFAULT, "You gained " + expString);
        sendTextMessage(message);

        g_game.addAnimatedText(std::to_string(exp), position, TEXTCOLOR_WHITE);

        SpectatorVec spectators;
        g_game.map.getSpectators(spectators, position, false, true);
        spectators.erase(this);
        if (!spectators.empty()) {
            message.type = MESSAGE_STATUS_DEFAULT;
            message.text = getName() + " gained " + expString;
            for (Creature* spectator : spectators) {
                spectator->getPlayer()->sendTextMessage(message);
            }
        }
    }

    uint32_t prevLevel = level;
    while (experience >= nextLevelExp) {
        ++level;
        healthMax += vocation->getHPGain();
        health += vocation->getHPGain();
        manaMax += vocation->getManaGain();
        mana += vocation->getManaGain();
        capacity += vocation->getCapGain();

        currLevelExp = nextLevelExp;
        nextLevelExp = Player::getExpForLevel(level + 1);
        if (currLevelExp >= nextLevelExp) {
            //player has reached max level
            break;
        }
    }

    if (prevLevel != level) {
        health = getMaxHealth();
        mana = getMaxMana();

        updateBaseSpeed();
        setBaseSpeed(getBaseSpeed());

        g_game.changeSpeed(this, 0);
        g_game.addCreatureHealth(this);

        const uint32_t protectionLevel = static_cast<uint32_t>(g_config.getNumber(ConfigManager::PROTECTION_LEVEL));
        if (prevLevel < protectionLevel && level >= protectionLevel) {
            g_game.updateCreatureWalkthrough(this);
        }

        if (party) {
            party->updateSharedExperience();
        }

        g_creatureEvents->playerAdvance(this, SKILL_LEVEL, prevLevel, level);

        sendTextMessage(MESSAGE_EVENT_ADVANCE, fmt::format("You advanced from Level {:d} to Level {:d}.", prevLevel, level));
    }

    if (nextLevelExp > currLevelExp) {
        levelPercent = Player::getPercentLevel(experience - currLevelExp, nextLevelExp - currLevelExp);
    } else {
        levelPercent = 0;
    }
    sendStats();
}

void Player::removeExperience(uint64_t exp, bool sendText/* = false*/)
{
    if (experience == 0 || exp == 0) {
        return;
    }

    g_events->eventPlayerOnLoseExperience(this, exp);
    if (exp == 0) {
        return;
    }

    uint64_t lostExp = experience;
    experience = std::max<int64_t>(0, experience - exp);

    if (sendText) {
        lostExp -= experience;

        std::string expString = std::to_string(lostExp) + (lostExp != 1 ? " experience points." : " experience point.");

        TextMessage message(MESSAGE_STATUS_DEFAULT, "You lost " + expString);
        sendTextMessage(message);

        g_game.addAnimatedText(std::to_string(lostExp), position, TEXTCOLOR_RED);

        SpectatorVec spectators;
        g_game.map.getSpectators(spectators, position, false, true);
        spectators.erase(this);
        if (!spectators.empty()) {
            message.type = MESSAGE_STATUS_DEFAULT;
            message.text = getName() + " lost " + expString;
            for (Creature* spectator : spectators) {
                spectator->getPlayer()->sendTextMessage(message);
            }
        }
    }

    uint32_t oldLevel = level;
    uint64_t currLevelExp = Player::getExpForLevel(level);

    while (level > 1 && experience < currLevelExp) {
        --level;
        healthMax = std::max<int32_t>(0, healthMax - vocation->getHPGain());
        manaMax = std::max<int32_t>(0, manaMax - vocation->getManaGain());
        capacity = std::max<int32_t>(0, capacity - vocation->getCapGain());
        currLevelExp = Player::getExpForLevel(level);
    }

    if (oldLevel != level) {
        health = getMaxHealth();
        mana = getMaxMana();

        updateBaseSpeed();
        setBaseSpeed(getBaseSpeed());

        g_game.changeSpeed(this, 0);
        g_game.addCreatureHealth(this);

        const uint32_t protectionLevel = static_cast<uint32_t>(g_config.getNumber(ConfigManager::PROTECTION_LEVEL));
        if (oldLevel >= protectionLevel && level < protectionLevel) {
            g_game.updateCreatureWalkthrough(this);
        }

        if (party) {
            party->updateSharedExperience();
        }

        sendTextMessage(MESSAGE_EVENT_ADVANCE, fmt::format("You were downgraded from Level {:d} to Level {:d}.", oldLevel, level));
    }

    uint64_t nextLevelExp = Player::getExpForLevel(level + 1);
    if (nextLevelExp > currLevelExp) {
        levelPercent = Player::getPercentLevel(experience - currLevelExp, nextLevelExp - currLevelExp);
    } else {
        levelPercent = 0;
    }
    sendStats();
}

uint8_t Player::getPercentLevel(uint64_t count, uint64_t nextLevelCount)
{
    if (nextLevelCount == 0) {
        return 0;
    }

    uint8_t result = (count * 100) / nextLevelCount;
    if (result > 100) {
        return 0;
    }
    return result;
}

void Player::onBlockHit()
{
    if (shieldBlockCount > 0) {
        --shieldBlockCount;

        if (hasShield()) {
            addSkillAdvance(SKILL_SHIELD, 1);
        }
    }
}
player.cpp
It's probably what I mentioned on my edit on my last post, try replacing with the last edit on my post marked as the solution.
 
the same Monsters now give very low experience levels
Looking at your addExperience function it seems like for some reason you don't have the following lines after calculating the bonus from monster levels.


C++:
    g_events->eventPlayerOnGainExperience(this, source, exp, rawExp);
    if (exp == 0) {
        return;
    }

I believe you may have deleted it by mistake, that's why you started getting the warning about rawExp not being referenced.

1715640077211.png
 
Solution
Back
Top