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

[7.72] OTHire 0.0.1b - Based in OTServ Trunk (Latest)

No I don't think it's fixed but it's pretty easy to implement, I have done it to my branch, I'll just have to look for it, I'm at work at the moment, I could post it when I get back from work.

By the way, the real Cipsoft config is < 5.
where's your branch (send link and I 'll check)
 
Add this to your Configmanager.cpp:


Code:
m_confInteger[LEVEL_TO_ROOK] = getGlobalNumber(L, "LevelToRook", 5);
m_confInteger[ROOK_TEMPLE_ID] = getGlobalNumber(L, "RookTempleId", 1);

Add this to your configmanager.h:

Code:
LEVEL_TO_ROOK,
ROOK_TEMPLE_ID,

Add this to your players.cpp:

Code:
void Player::sendToRook()
{
    setVocation(VOCATION_NONE);

    level = 1;
    healthMax = 150;
    manaMax = 0;
    manaSpent = 0;
    magLevel= 0;
#ifdef __PROTOCOL_76__
    soul = 100;
    soulMax = 100;
#endif // __PROTOCOL_76__
    capacity = 400;
    experience = 0;

    for (int32_t i = SKILL_FIRST; i <= SKILL_LAST; ++i) {
        skills[i][SKILL_LEVEL]= 10;
        skills[i][SKILL_TRIES]= 0;
    }

    for (int32_t i = SLOT_FIRST; i < SLOT_LAST; ++i) {
        if (inventory[i]) {
            g_game.internalRemoveItem(inventory[i]);
        }
    }

    __internalAddThing(SLOT_BACKPACK, Item::CreateItem(1987));
    __internalAddThing(SLOT_RIGHT, Item::CreateItem(2382));
    if (getSex() == PLAYERSEX_MALE)
        __internalAddThing(SLOT_ARMOR, Item::CreateItem(2650));
    else
        __internalAddThing(SLOT_ARMOR, Item::CreateItem(2651));

    Town* town = Towns::getInstance().getTown(g_config.getNumber(ConfigManager::ROOK_TEMPLE_ID));
    if (town) {
        setTown(town->getTownID());
        loginPosition = town->getTemplePosition();
    }
}

Now compare this Function with your Die Function and add what needs to be added....( I know, a little work, but it's quite easy to learn).

Code:
void Player::die()
{
    for(ConditionList::iterator it = conditions.begin(); it != conditions.end();){
        if((*it)->isPersistent()){
            Condition* condition = *it;
            it = conditions.erase(it);

            condition->endCondition(this, CONDITIONEND_DIE);
            onEndCondition(condition->getType());
            delete condition;
        }
        else{
            ++it;
        }
    }

    loginPosition = masterPos;

    if(skillLoss){
        //Magic level loss
        uint32_t sumMana = 0;
        int32_t lostMana = 0;

        //sum up all the mana
        for(uint32_t i = 1; i <= magLevel; ++i){
            sumMana += vocation->getReqMana(i);
        }

        sumMana += manaSpent;

        lostMana = (int32_t)std::ceil(sumMana * ((double)lossPercent[LOSS_MANASPENT]/100));

        while((uint32_t)lostMana > manaSpent && magLevel > 0){
            lostMana -= manaSpent;
            manaSpent = vocation->getReqMana(magLevel);
            magLevel--;
        }

        manaSpent = std::max((int32_t)0, (int32_t)manaSpent - lostMana);
        magLevelPercent = Player::getPercentLevel(manaSpent, vocation->getReqMana(magLevel + 1));

        //Skill loss
        uint32_t lostSkillTries;
        uint32_t sumSkillTries;
        for(uint32_t i = 0; i <= 6; ++i){  //for each skill
            lostSkillTries = 0;         //reset to 0
            sumSkillTries = 0;

            for(uint32_t c = 11; c <= skills[i][SKILL_LEVEL]; ++c) { //sum up all required tries for all skill levels
                sumSkillTries += vocation->getReqSkillTries(i, c);
            }

            sumSkillTries += skills[i][SKILL_TRIES];
            lostSkillTries = (uint32_t)std::ceil(sumSkillTries * ((double)lossPercent[LOSS_SKILLTRIES]/100));

            while(lostSkillTries > skills[i][SKILL_TRIES]){
                lostSkillTries -= skills[i][SKILL_TRIES];
                skills[i][SKILL_TRIES] = vocation->getReqSkillTries(i, skills[i][SKILL_LEVEL]);
                if(skills[i][SKILL_LEVEL] > 10){
                    skills[i][SKILL_LEVEL]--;
                }
                else{
                    skills[i][SKILL_LEVEL] = 10;
                    skills[i][SKILL_TRIES] = 0;
                    lostSkillTries = 0;
                    break;
                }
            }

            skills[i][SKILL_TRIES] = std::max((int32_t)0, (int32_t)(skills[i][SKILL_TRIES] - lostSkillTries));
        }
        //

        //Level loss
        uint32_t newLevel = level;
        uint32_t oldLevel = level; 
        while((uint64_t)(experience - getLostExperience()) < Player::getExpForLevel(newLevel)){
            if(newLevel > 1)
                newLevel--;
            else
                break;
        }

        if(newLevel != level){

            uint32_t levelToRook = g_config.getNumber(ConfigManager::LEVEL_TO_ROOK);
            bool rooked = false;
            if((newLevel <= levelToRook) && getVocationId() != 0) {
                sendToRook();
                rooked = true;
            }

            if (rooked) {
                newLevel = 1;
            }

            std::stringstream lvMsg;
            lvMsg << "You were downgraded from level " << oldLevel << " to level " << newLevel << ".";
            sendTextMessage(MSG_EVENT_ADVANCE, lvMsg.str());
        }
    }
}

Now in your player.h add this line:
Code:
void sendToRook();

Just before these lines:

Code:
void onDie();
void die();


Voila, it should be working.
 
Add this to your Configmanager.cpp:


Code:
m_confInteger[LEVEL_TO_ROOK] = getGlobalNumber(L, "LevelToRook", 5);
m_confInteger[ROOK_TEMPLE_ID] = getGlobalNumber(L, "RookTempleId", 1);

Add this to your configmanager.h:

Code:
LEVEL_TO_ROOK,
ROOK_TEMPLE_ID,

Add this to your players.cpp:

Code:
void Player::sendToRook()
{
    setVocation(VOCATION_NONE);

    level = 1;
    healthMax = 150;
    manaMax = 0;
    manaSpent = 0;
    magLevel= 0;
#ifdef __PROTOCOL_76__
    soul = 100;
    soulMax = 100;
#endif // __PROTOCOL_76__
    capacity = 400;
    experience = 0;

    for (int32_t i = SKILL_FIRST; i <= SKILL_LAST; ++i) {
        skills[i][SKILL_LEVEL]= 10;
        skills[i][SKILL_TRIES]= 0;
    }

    for (int32_t i = SLOT_FIRST; i < SLOT_LAST; ++i) {
        if (inventory[i]) {
            g_game.internalRemoveItem(inventory[i]);
        }
    }

    __internalAddThing(SLOT_BACKPACK, Item::CreateItem(1987));
    __internalAddThing(SLOT_RIGHT, Item::CreateItem(2382));
    if (getSex() == PLAYERSEX_MALE)
        __internalAddThing(SLOT_ARMOR, Item::CreateItem(2650));
    else
        __internalAddThing(SLOT_ARMOR, Item::CreateItem(2651));

    Town* town = Towns::getInstance().getTown(g_config.getNumber(ConfigManager::ROOK_TEMPLE_ID));
    if (town) {
        setTown(town->getTownID());
        loginPosition = town->getTemplePosition();
    }
}

Now compare this Function with your Die Function and add what needs to be added....( I know, a little work, but it's quite easy to learn).

Code:
void Player::die()
{
    for(ConditionList::iterator it = conditions.begin(); it != conditions.end();){
        if((*it)->isPersistent()){
            Condition* condition = *it;
            it = conditions.erase(it);

            condition->endCondition(this, CONDITIONEND_DIE);
            onEndCondition(condition->getType());
            delete condition;
        }
        else{
            ++it;
        }
    }

    loginPosition = masterPos;

    if(skillLoss){
        //Magic level loss
        uint32_t sumMana = 0;
        int32_t lostMana = 0;

        //sum up all the mana
        for(uint32_t i = 1; i <= magLevel; ++i){
            sumMana += vocation->getReqMana(i);
        }

        sumMana += manaSpent;

        lostMana = (int32_t)std::ceil(sumMana * ((double)lossPercent[LOSS_MANASPENT]/100));

        while((uint32_t)lostMana > manaSpent && magLevel > 0){
            lostMana -= manaSpent;
            manaSpent = vocation->getReqMana(magLevel);
            magLevel--;
        }

        manaSpent = std::max((int32_t)0, (int32_t)manaSpent - lostMana);
        magLevelPercent = Player::getPercentLevel(manaSpent, vocation->getReqMana(magLevel + 1));

        //Skill loss
        uint32_t lostSkillTries;
        uint32_t sumSkillTries;
        for(uint32_t i = 0; i <= 6; ++i){  //for each skill
            lostSkillTries = 0;         //reset to 0
            sumSkillTries = 0;

            for(uint32_t c = 11; c <= skills[i][SKILL_LEVEL]; ++c) { //sum up all required tries for all skill levels
                sumSkillTries += vocation->getReqSkillTries(i, c);
            }

            sumSkillTries += skills[i][SKILL_TRIES];
            lostSkillTries = (uint32_t)std::ceil(sumSkillTries * ((double)lossPercent[LOSS_SKILLTRIES]/100));

            while(lostSkillTries > skills[i][SKILL_TRIES]){
                lostSkillTries -= skills[i][SKILL_TRIES];
                skills[i][SKILL_TRIES] = vocation->getReqSkillTries(i, skills[i][SKILL_LEVEL]);
                if(skills[i][SKILL_LEVEL] > 10){
                    skills[i][SKILL_LEVEL]--;
                }
                else{
                    skills[i][SKILL_LEVEL] = 10;
                    skills[i][SKILL_TRIES] = 0;
                    lostSkillTries = 0;
                    break;
                }
            }

            skills[i][SKILL_TRIES] = std::max((int32_t)0, (int32_t)(skills[i][SKILL_TRIES] - lostSkillTries));
        }
        //

        //Level loss
        uint32_t newLevel = level;
        uint32_t oldLevel = level;
        while((uint64_t)(experience - getLostExperience()) < Player::getExpForLevel(newLevel)){
            if(newLevel > 1)
                newLevel--;
            else
                break;
        }

        if(newLevel != level){

            uint32_t levelToRook = g_config.getNumber(ConfigManager::LEVEL_TO_ROOK);
            bool rooked = false;
            if((newLevel <= levelToRook) && getVocationId() != 0) {
                sendToRook();
                rooked = true;
            }

            if (rooked) {
                newLevel = 1;
            }

            std::stringstream lvMsg;
            lvMsg << "You were downgraded from level " << oldLevel << " to level " << newLevel << ".";
            sendTextMessage(MSG_EVENT_ADVANCE, lvMsg.str());
        }
    }
}

Now in your player.h add this line:
Code:
void sendToRook();

Just before these lines:

Code:
void onDie();
void die();


Voila, it should be working.
Great Work!! You are awesome! thanks
 
@Okke Othire die seems to be a little different than yours:

Code:
void Player::die()
{
    ConditionEnd_t conditionEndReason = CONDITIONEND_DIE;
    if(getZone() == ZONE_PVP){
        conditionEndReason = CONDITIONEND_ABORT;
    }

    for(ConditionList::iterator it = conditions.begin(); it != conditions.end();){
        if((*it)->isPersistent()){
            Condition* condition = *it;
            it = conditions.erase(it);

            condition->endCondition(this, conditionEndReason);

            bool lastCondition = !hasCondition(condition->getType(), false);
            onEndCondition(condition->getType(), lastCondition);
            delete condition;
        }
        else{
            ++it;
        }
    }

    if(getZone() != ZONE_PVP){
        loginPosition = masterPos;

        if(skillLoss){
            uint64_t expLost = getLostExperience();

            //Level loss
            removeExperience(expLost, false);
            double lostPercent = 1. - (double(experience - expLost) / double(experience)); // 0.1 if 10% was lost

            //Magic level loss
            uint64_t sumMana = 0;
            uint64_t lostMana = 0;

            for(uint32_t i = 1; i <= magLevel; ++i){
                sumMana += vocation->getReqMana(i);
            }

            sumMana += manaSpent;

            double lostPercentMana = lostPercent * lossPercent[LOSS_MANASPENT] / 100;
            lostMana = (uint64_t)std::ceil(sumMana * lostPercentMana);

            while((uint64_t)lostMana > manaSpent && magLevel > 0){
                lostMana -= manaSpent;
                manaSpent = vocation->getReqMana(magLevel);
                magLevel--;
            }

            manaSpent = std::max((uint64_t)0, (uint64_t)manaSpent - lostMana);
            magLevelPercent = Player::getPercentLevel(manaSpent, vocation->getReqMana(magLevel + 1));

            //Skill loss
            uint32_t lostSkillTries;
            uint32_t sumSkillTries;
            for(uint32_t i = 0; i <= 6; ++i){
                lostSkillTries = 0;
                sumSkillTries = 0;

                for(uint32_t c = 11; c <= skills[i][SKILL_LEVEL]; ++c) {
                    sumSkillTries += vocation->getReqSkillTries(i, c);
                }

                sumSkillTries += skills[i][SKILL_TRIES];
                double lossPercentSkill = lostPercent * lossPercent[LOSS_SKILLTRIES] / 100;
                lostSkillTries = (uint32_t)std::ceil(sumSkillTries * lossPercentSkill);

                while(lostSkillTries > skills[i][SKILL_TRIES]){
                    lostSkillTries -= skills[i][SKILL_TRIES];
                    skills[i][SKILL_TRIES] = vocation->getReqSkillTries(i, skills[i][SKILL_LEVEL]);
                    if(skills[i][SKILL_LEVEL] > 10){
                        skills[i][SKILL_LEVEL]--;
                    }
                    else{
                        skills[i][SKILL_LEVEL] = 10;
                        skills[i][SKILL_TRIES] = 0;
                        lostSkillTries = 0;
                        break;
                    }
                }

                skills[i][SKILL_TRIES] = std::max((int32_t)0, (int32_t)(skills[i][SKILL_TRIES] - lostSkillTries));
            }
        }

        Creature::die();
        std::string death_msg = g_config.getString(ConfigManager::DEATH_MSG);
        if(death_msg.length() > 0)
            sendTextMessage(MSG_EVENT_DEFAULT, death_msg);
    }
    else{
        preSave();
        setDropLoot(true);
        setLossSkill(true);
        sendStats();
        g_game.internalTeleport(this, getTemplePosition());
        g_game.addCreatureHealth(this);
        onThink(EVENT_CREATURE_THINK_INTERVAL);
    }
}

Item* Player::dropCorpse()
{
    if(getZone() != ZONE_PVP){
        return Creature::dropCorpse();
    }

    return NULL;
}

Item* Player::createCorpse()
{
    Item* corpse = Creature::createCorpse();
    if(corpse && corpse->getContainer()){
        std::stringstream ss;

        ss << "You recognize " << getNameDescription() << ".";

        DeathList killers = getKillers(0);
        if(!killers.empty() && (*killers.begin()).isCreatureKill()){
            ss << " " << playerSexSubjectString(getSex()) << " was killed by "
                << ((*killers.begin()).getKillerCreature())->getNameDescription() << ".";
        }

        corpse->setSpecialDescription(ss.str());
    }

    return corpse;
}
 
Well well, the condition names are different declared, as I said you'd have to compare, this requires a little of code understanding, if you can't implement it, I can help you with it once Im home, this will be in about 6-7 hours. We can do it with skype and then we can post a reply here with the fix Pm me and we'll take a look at it together!
 
I tried to update player.cpp:
Code:
void Player::die()
{
    ConditionEnd_t conditionEndReason = CONDITIONEND_DIE;
    if(getZone() == ZONE_PVP){
        conditionEndReason = CONDITIONEND_ABORT;
    }

    for(ConditionList::iterator it = conditions.begin(); it != conditions.end();){
        if((*it)->isPersistent()){
            Condition* condition = *it;
            it = conditions.erase(it);

            condition->endCondition(this, conditionEndReason);

            bool lastCondition = !hasCondition(condition->getType(), false);
            onEndCondition(condition->getType(), lastCondition);
            delete condition;
        }
        else{
            ++it;
        }
    }

    if(getZone() != ZONE_PVP){
        loginPosition = masterPos;

        if(skillLoss){
            uint64_t expLost = getLostExperience();

            //Level loss
            removeExperience(expLost, false);
            double lostPercent = 1. - (double(experience - expLost) / double(experience)); // 0.1 if 10% was lost

            //Magic level loss
            uint64_t sumMana = 0;
            uint64_t lostMana = 0;

            for(uint32_t i = 1; i <= magLevel; ++i){
                sumMana += vocation->getReqMana(i);
            }

            sumMana += manaSpent;

            double lostPercentMana = lostPercent * lossPercent[LOSS_MANASPENT] / 100;
            lostMana = (uint64_t)std::ceil(sumMana * lostPercentMana);

            while((uint64_t)lostMana > manaSpent && magLevel > 0){
                lostMana -= manaSpent;
                manaSpent = vocation->getReqMana(magLevel);
                magLevel--;
            }

            manaSpent = std::max((uint64_t)0, (uint64_t)manaSpent - lostMana);
            magLevelPercent = Player::getPercentLevel(manaSpent, vocation->getReqMana(magLevel + 1));

            //Skill loss
            uint32_t lostSkillTries;
            uint32_t sumSkillTries;
            for(uint32_t i = 0; i <= 6; ++i){
                lostSkillTries = 0;
                sumSkillTries = 0;

                for(uint32_t c = 11; c <= skills[i][SKILL_LEVEL]; ++c) {
                    sumSkillTries += vocation->getReqSkillTries(i, c);
                }

                sumSkillTries += skills[i][SKILL_TRIES];
                double lossPercentSkill = lostPercent * lossPercent[LOSS_SKILLTRIES] / 100;
                lostSkillTries = (uint32_t)std::ceil(sumSkillTries * lossPercentSkill);

                while(lostSkillTries > skills[i][SKILL_TRIES]){
                    lostSkillTries -= skills[i][SKILL_TRIES];
                    skills[i][SKILL_TRIES] = vocation->getReqSkillTries(i, skills[i][SKILL_LEVEL]);
                    if(skills[i][SKILL_LEVEL] > 10){
                        skills[i][SKILL_LEVEL]--;
                    }
                    else{
                        skills[i][SKILL_LEVEL] = 10;
                        skills[i][SKILL_TRIES] = 0;
                        lostSkillTries = 0;
                        break;
                    }
                }

                skills[i][SKILL_TRIES] = std::max((int32_t)0, (int32_t)(skills[i][SKILL_TRIES] - lostSkillTries));
            }
       
                //Level loss
                uint32_t newLevel = level;
                uint32_t oldLevel = level;
                while((uint64_t)(experience - getLostExperience()) < Player::getExpForLevel(newLevel)){
                    if(newLevel > 1)
                        newLevel--;
                    else
                        break;
                }

                if(newLevel != level){

                    uint32_t levelToRook = g_config.getNumber(ConfigManager::LEVEL_TO_ROOK);
                    bool rooked = false;
                    if((newLevel <= levelToRook) && getVocationId() != 0) {
                        sendToRook();
                        rooked = true;
                    }

                    if (rooked) {
                        newLevel = 1;
                    }

                    std::stringstream lvMsg;
                    lvMsg << "You were downgraded from level " << oldLevel << " to level " << newLevel << ".";
                    sendTextMessage(MSG_EVENT_ADVANCE, lvMsg.str());
                }
       
        }

        Creature::die();
        std::string death_msg = g_config.getString(ConfigManager::DEATH_MSG);
        if(death_msg.length() > 0)
            sendTextMessage(MSG_EVENT_DEFAULT, death_msg);
    }
    else{
        preSave();
        setDropLoot(true);
        setLossSkill(true);
        sendStats();
        g_game.internalTeleport(this, getTemplePosition());
        g_game.addCreatureHealth(this);
        onThink(EVENT_CREATURE_THINK_INTERVAL);
    }
}

But the problem when I recompile is:
Code:
1>player.cpp(2368): error C2065: 'Town' : undeclared identifier
1>player.cpp(2368): error C2653: 'Towns' : is not a class or namespace name
1>player.cpp(2368): error C2228: left of '.getTown' must have class/struct/union
1>          type is ''unknown-type''
1>player.cpp(2368): error C3861: 'getInstance': identifier not found
1>player.cpp(2370): error C2227: left of '->getTownID' must point to class/struct/union/generic type
1>          type is 'uint32_t'
1>player.cpp(2371): error C2227: left of '->getTemplePosition' must point to class/struct/union/generic type
1>          type is 'uint32_t'
 
Can't edit my last post.

The problem seems to be with:
Code:
void Player::sendToRook()
{
    setVocation(VOCATION_NONE);

    level = 1;
    healthMax = 150;
    manaMax = 0;
    manaSpent = 0;
    magLevel= 0;
#ifdef __PROTOCOL_76__
    soul = 100;
    soulMax = 100;
#endif // __PROTOCOL_76__
    capacity = 400;
    experience = 0;

    for (int32_t i = SKILL_FIRST; i <= SKILL_LAST; ++i) {
        skills[i][SKILL_LEVEL]= 10;
        skills[i][SKILL_TRIES]= 0;
    }

    for (int32_t i = SLOT_FIRST; i < SLOT_LAST; ++i) {
        if (inventory[i]) {
            g_game.internalRemoveItem(inventory[i]);
        }
    }

    __internalAddThing(SLOT_BACKPACK, Item::CreateItem(1987));
    __internalAddThing(SLOT_RIGHT, Item::CreateItem(2382));
    if (getSex() == PLAYERSEX_MALE)
        __internalAddThing(SLOT_ARMOR, Item::CreateItem(2650));
    else
        __internalAddThing(SLOT_ARMOR, Item::CreateItem(2651));

    Town* town = Towns::getInstance().getTown(g_config.getNumber(ConfigManager::ROOK_TEMPLE_ID));
    if (town) {
        setTown(town->getTownID());
        loginPosition = town->getTemplePosition();
    }
}
 
Hello,

as I said, we can compare when I get home :D :D.

I can see, OTHire sources have Town defined as town.

getTemplePosition and other functions are defined as other uint type. ( you can check it on player.h ).

I'm sorry for not being able to give you an exact answer for your problem, I'll work on this one once I'm home!
 
Sorry for the double post again:

You need to add this in your player.cpp:

Code:
#include "town.h"

Now on your player.h look for this line:

Code:
const Position& getTemplePosition() const {return masterPos;}

Insert now this 2 lines:

Code:
uint32_t getTown() const {return town;}
void setTown(uint32_t _town) {town = _town;}

Now check also on player.h for these lines:

Code:
std::string name;
std::string nameDescription;
uint32_t guid;

Add this line to it:

Code:
uint32_t town;

It should work now...If not we should compare town.h

Just post the errors if there is any! :)
 
Sorry for the double
Code:
configmanager.cpp(204): warning C4789: destination of memory copy is too small
configmanager.cpp(205): warning C4789: destination of memory copy is too small
post again:

You need to add this in your player.cpp:

Code:
#include "town.h"

Now on your player.h look for this line:

Code:
const Position& getTemplePosition() const {return masterPos;}

Insert now this 2 lines:

Code:
uint32_t getTown() const {return town;}
void setTown(uint32_t _town) {town = _town;}

Now check also on player.h for these lines:

Code:
std::string name;
std::string nameDescription;
uint32_t guid;

Add this line to it:

Code:
uint32_t town;

It should work now...If not we should compare town.h

Just post the errors if there is any! :)
It seems to work, only two warnings on compile:
Code:
configmanager.cpp(204): warning C4789: destination of memory copy is too small
configmanager.cpp(205): warning C4789: destination of memory copy is too small
Refered to:
Code:
    m_confInteger[LEVEL_TO_ROOK] = getGlobalNumber(L, "LevelToRook", 5);
    m_confInteger[ROOK_TEMPLE_ID] = getGlobalNumber(L, "RookTempleId", 11);
 
Sorry for the double post again:

You need to add this in your player.cpp:

Code:
#include "town.h"

Now on your player.h look for this line:

Code:
const Position& getTemplePosition() const {return masterPos;}

Insert now this 2 lines:

Code:
uint32_t getTown() const {return town;}
void setTown(uint32_t _town) {town = _town;}

Now check also on player.h for these lines:

Code:
std::string name;
std::string nameDescription;
uint32_t guid;

Add this line to it:

Code:
uint32_t town;

It should work now...If not we should compare town.h

Just post the errors if there is any! :)
Server crashed an the log returned:
:: Loading data/monster/monsters.xml... Unhandled exception. Generating minidump...
 
Replace these lines from the place they are:
Code:
 m_confInteger[LEVEL_TO_ROOK] = getGlobalNumber(L, "LevelToRook", 5);
m_confInteger[ROOK_TEMPLE_ID] = getGlobalNumber(L, "RookTempleId", 11);

under on your configmanager.cpp:
Code:
m_confInteger[IPBANISHMENT_LENGTH] = getGlobalNumber(L, "ip_banishment_length", 86400);

and replace also these lines from configmanager.h:

Code:
LEVEL_TO_ROOK,
ROOK_TEMPLE_ID,

under on your configmanager.h:

Code:
enum integer_config_t {
 
Sorry for the last 2 posts, was my fault.
Started from scratch guided by your indications and @tarantonio's help and it worked!

Not easy to get level 5!!
We made a server to check and there are the screens:
vy3CjwO.jpg

yVNeH07.jpg
 
Sweet man!

Now please post the fix so everyone has it shortened here, keep the community helping!
 
ROOKGAARD SYSTEM
Tested and working 100%
Credits: @Okke (Scripts) - Me (Join all together and test ;P)

Add this to your Configmanager.cpp:


Code:
m_confInteger[LEVEL_TO_ROOK] = getGlobalNumber(L, "LevelToRook", 5);
m_confInteger[ROOK_TEMPLE_ID] = getGlobalNumber(L, "RookTempleId", 1);

Add this to your configmanager.h:

Code:
LEVEL_TO_ROOK,
ROOK_TEMPLE_ID,

Add this to your players.cpp:

Code:
#include "town.h"

And:

Code:
void Player::sendToRook()
{
    setVocation(VOCATION_NONE);

    level = 1;
    healthMax = 150;
    manaMax = 0;
    manaSpent = 0;
    magLevel= 0;
#ifdef __PROTOCOL_76__
    soul = 100;
    soulMax = 100;
#endif // __PROTOCOL_76__
    capacity = 400;
    experience = 0;

    for (int32_t i = SKILL_FIRST; i <= SKILL_LAST; ++i) {
        skills[i][SKILL_LEVEL]= 10;
        skills[i][SKILL_TRIES]= 0;
    }

    for (int32_t i = SLOT_FIRST; i < SLOT_LAST; ++i) {
        if (inventory[i]) {
            g_game.internalRemoveItem(inventory[i]);
        }
    }

    __internalAddThing(SLOT_BACKPACK, Item::CreateItem(1987));
    __internalAddThing(SLOT_RIGHT, Item::CreateItem(2382));
    if (getSex() == PLAYERSEX_MALE)
        __internalAddThing(SLOT_ARMOR, Item::CreateItem(2650));
    else
        __internalAddThing(SLOT_ARMOR, Item::CreateItem(2651));

    Town* town = Towns::getInstance().getTown(g_config.getNumber(ConfigManager::ROOK_TEMPLE_ID));
    if (town) {
        setTown(town->getTownID());
        loginPosition = town->getTemplePosition();
    }
}

Now compare this Function with your Die Function and add what needs to be added....( I know, a little work, but it's quite easy to learn).

Code:
void Player::die()
{
    for(ConditionList::iterator it = conditions.begin(); it != conditions.end();){
        if((*it)->isPersistent()){
            Condition* condition = *it;
            it = conditions.erase(it);

            condition->endCondition(this, CONDITIONEND_DIE);
            onEndCondition(condition->getType());
            delete condition;
        }
        else{
            ++it;
        }
    }

    loginPosition = masterPos;

    if(skillLoss){
        //Magic level loss
        uint32_t sumMana = 0;
        int32_t lostMana = 0;

        //sum up all the mana
        for(uint32_t i = 1; i <= magLevel; ++i){
            sumMana += vocation->getReqMana(i);
        }

        sumMana += manaSpent;

        lostMana = (int32_t)std::ceil(sumMana * ((double)lossPercent[LOSS_MANASPENT]/100));

        while((uint32_t)lostMana > manaSpent && magLevel > 0){
            lostMana -= manaSpent;
            manaSpent = vocation->getReqMana(magLevel);
            magLevel--;
        }

        manaSpent = std::max((int32_t)0, (int32_t)manaSpent - lostMana);
        magLevelPercent = Player::getPercentLevel(manaSpent, vocation->getReqMana(magLevel + 1));

        //Skill loss
        uint32_t lostSkillTries;
        uint32_t sumSkillTries;
        for(uint32_t i = 0; i <= 6; ++i){  //for each skill
            lostSkillTries = 0;         //reset to 0
            sumSkillTries = 0;

            for(uint32_t c = 11; c <= skills[i][SKILL_LEVEL]; ++c) { //sum up all required tries for all skill levels
                sumSkillTries += vocation->getReqSkillTries(i, c);
            }

            sumSkillTries += skills[i][SKILL_TRIES];
            lostSkillTries = (uint32_t)std::ceil(sumSkillTries * ((double)lossPercent[LOSS_SKILLTRIES]/100));

            while(lostSkillTries > skills[i][SKILL_TRIES]){
                lostSkillTries -= skills[i][SKILL_TRIES];
                skills[i][SKILL_TRIES] = vocation->getReqSkillTries(i, skills[i][SKILL_LEVEL]);
                if(skills[i][SKILL_LEVEL] > 10){
                    skills[i][SKILL_LEVEL]--;
                }
                else{
                    skills[i][SKILL_LEVEL] = 10;
                    skills[i][SKILL_TRIES] = 0;
                    lostSkillTries = 0;
                    break;
                }
            }

            skills[i][SKILL_TRIES] = std::max((int32_t)0, (int32_t)(skills[i][SKILL_TRIES] - lostSkillTries));
        }
        //

        //Level loss
        uint32_t newLevel = level;
        uint32_t oldLevel = level;
        while((uint64_t)(experience - getLostExperience()) < Player::getExpForLevel(newLevel)){
            if(newLevel > 1)
                newLevel--;
            else
                break;
        }

        if(newLevel != level){

            uint32_t levelToRook = g_config.getNumber(ConfigManager::LEVEL_TO_ROOK);
            bool rooked = false;
            if((newLevel <= levelToRook) && getVocationId() != 0) {
                sendToRook();
                rooked = true;
            }

            if (rooked) {
                newLevel = 1;
            }

            std::stringstream lvMsg;
            lvMsg << "You were downgraded from level " << oldLevel << " to level " << newLevel << ".";
            sendTextMessage(MSG_EVENT_ADVANCE, lvMsg.str());
        }
    }
}

Now in your player.h add this line:
Code:
void sendToRook();

Just before these lines:

Code:
void onDie();
void die();

Screens from the test server:
vy3CjwO.jpg


yVNeH07.jpg
 
I can't edit my last post grrrr...

I made a mistake with the player.cpp part, here is the OK version:
Code:
void Player::die()
{
    ConditionEnd_t conditionEndReason = CONDITIONEND_DIE;
    if(getZone() == ZONE_PVP){
        conditionEndReason = CONDITIONEND_ABORT;
    }

    for(ConditionList::iterator it = conditions.begin(); it != conditions.end();){
        if((*it)->isPersistent()){
            Condition* condition = *it;
            it = conditions.erase(it);

            condition->endCondition(this, conditionEndReason);

            bool lastCondition = !hasCondition(condition->getType(), false);
            onEndCondition(condition->getType(), lastCondition);
            delete condition;
        }
        else{
            ++it;
        }
    }

    if(getZone() != ZONE_PVP){
        loginPosition = masterPos;

        if(skillLoss){
            uint64_t expLost = getLostExperience();

            //Level loss
            removeExperience(expLost, false);
            double lostPercent = 1. - (double(experience - expLost) / double(experience)); // 0.1 if 10% was lost

            //Magic level loss
            uint64_t sumMana = 0;
            uint64_t lostMana = 0;

            for(uint32_t i = 1; i <= magLevel; ++i){
                sumMana += vocation->getReqMana(i);
            }

            sumMana += manaSpent;

            double lostPercentMana = lostPercent * lossPercent[LOSS_MANASPENT] / 100;
            lostMana = (uint64_t)std::ceil(sumMana * lostPercentMana);

            while((uint64_t)lostMana > manaSpent && magLevel > 0){
                lostMana -= manaSpent;
                manaSpent = vocation->getReqMana(magLevel);
                magLevel--;
            }

            manaSpent = std::max((uint64_t)0, (uint64_t)manaSpent - lostMana);
            magLevelPercent = Player::getPercentLevel(manaSpent, vocation->getReqMana(magLevel + 1));

            //Skill loss
            uint32_t lostSkillTries;
            uint32_t sumSkillTries;
            for(uint32_t i = 0; i <= 6; ++i){
                lostSkillTries = 0;
                sumSkillTries = 0;

                for(uint32_t c = 11; c <= skills[i][SKILL_LEVEL]; ++c) {
                    sumSkillTries += vocation->getReqSkillTries(i, c);
                }

                sumSkillTries += skills[i][SKILL_TRIES];
                double lossPercentSkill = lostPercent * lossPercent[LOSS_SKILLTRIES] / 100;
                lostSkillTries = (uint32_t)std::ceil(sumSkillTries * lossPercentSkill);

                while(lostSkillTries > skills[i][SKILL_TRIES]){
                    lostSkillTries -= skills[i][SKILL_TRIES];
                    skills[i][SKILL_TRIES] = vocation->getReqSkillTries(i, skills[i][SKILL_LEVEL]);
                    if(skills[i][SKILL_LEVEL] > 10){
                        skills[i][SKILL_LEVEL]--;
                    }
                    else{
                        skills[i][SKILL_LEVEL] = 10;
                        skills[i][SKILL_TRIES] = 0;
                        lostSkillTries = 0;
                        break;
                    }
                }

                skills[i][SKILL_TRIES] = std::max((int32_t)0, (int32_t)(skills[i][SKILL_TRIES] - lostSkillTries));
            }
           
            //Level loss
            uint32_t newLevel = level;
            uint32_t oldLevel = level;
            while((uint64_t)(experience - getLostExperience()) < Player::getExpForLevel(newLevel)){
                if(newLevel > 1)
                    newLevel--;
                else
                    break;
            }

            if(newLevel != level){

                uint32_t levelToRook = g_config.getNumber(ConfigManager::LEVEL_TO_ROOK);
                bool rooked = false;
                if((newLevel <= levelToRook) && getVocationId() != 0) {
                    sendToRook();
                    rooked = true;
                }

                if (rooked) {
                    newLevel = 1;
                }

                std::stringstream lvMsg;
                lvMsg << "You were downgraded from level " << oldLevel << " to level " << newLevel << ".";
                sendTextMessage(MSG_EVENT_ADVANCE, lvMsg.str());
            }
        }

        Creature::die();
        std::string death_msg = g_config.getString(ConfigManager::DEATH_MSG);
        if(death_msg.length() > 0)
            sendTextMessage(MSG_EVENT_DEFAULT, death_msg);
    }
    else{
        preSave();
        setDropLoot(true);
        setLossSkill(true);
        sendStats();
        g_game.internalTeleport(this, getTemplePosition());
        g_game.addCreatureHealth(this);
        onThink(EVENT_CREATURE_THINK_INTERVAL);
    }
}
 
Only for OTHire users, you should change the firstitems.lua to something like:
Code:
local firstItems = {2050, 2382}
function onLogin(cid)

    if getPlayerVocation(cid) == 0 and getPlayerLastLogin(cid) == 0 then
        if getPlayerLastLogin(cid) == 0 or getPlayerStorageValue(cid, STORAGE_ROOK) == 1 then
            for i = 1, #firstItems do
                doPlayerAddItem(cid, firstItems[i], 1)
            end
            doPlayerAddItem(cid, getPlayerSex(cid) == 0 and 2651 or 2650, 1)
            local bag = doPlayerAddItem(cid, 1987, 1)
            doAddContainerItem(bag, 2674, 1)
       end
    end
    return TRUE
end
And change the options on your website to only make rookgaard characters at start.
 
The only question now that I don't remember is the situation where you are rooked owning a house.
 
Back
Top