• 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 1.X+ automatic recognition from premium to free tfs 1.5 772

bpm91

Intermediate OT User
Joined
May 23, 2019
Messages
930
Solutions
7
Reaction score
127
Location
Brazil
YouTube
caruniawikibr
hi, I would like to know how do I configure the player when it is premium and free, and it relogs free, born in Thais for example. like in tibia global
 
Solution
You can try with this:

data/scripts/onlosspremium.lua
Lua:
local storage = 88888
local defaultCity = "Thais"

local creatureEvent = CreatureEvent("onLossPremium")

function creatureEvent.onLogin(player)
    if player:getStorageValue(storage) == -1 then
        player:setStorageValue(storage, player:isPremium() and 1 or 0)
    end
    if player:getPremiumEndsAt() < os.time() then
        if player:getStorageValue(storage) == 1 then
            player:setStorageValue(storage, 0)
            player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Your premium time has expired.")
            local thais = Town(defaultCity)
            player:setTown(thais)
            local thaisPos = thais:getTemplePosition()...
@Diarreamental
Tested in TFS 1.5 Nekiro 7.72

In player.cpp (look for death), before
C:
 //PASTE CODE BELOW HEREEEEEEEEEEEEEEEEEEEEEE
   } else {
        setSkillLoss(true);

Paste this code, where I write to do:
C:
        // Teleport players from mainland back to rookgaard
        if (g_config.getBoolean(ConfigManager::GLOBAL_ROOKSYSTEM)) {
            if (vocation->getId() != VOCATION_NONE && level <= static_cast<uint32_t>(g_config.getNumber(ConfigManager::ROOKGAARD_LEVEL_THRESHOLD))) {
                Town* rookTown = g_game.map.towns.getTown(g_config.getNumber(ConfigManager::ROOKGAARD_TOWN));
                if (rookTown) {
                    // Restart stats
                    level = 1;
                    experience = 0;
                    levelPercent = 0;
                    capacity = 40000; //400oz
                    health = 150;
                    healthMax = 150;
                    mana = 0;
                    manaMax = 0;
                    magLevel = 0;
                    magLevelPercent = 0;
                    manaSpent = 0;
                    setVocation(0);

                    // Restart skills
                    for (uint8_t i = SKILL_FIRST; i <= SKILL_LAST; ++i) { //for each skill
                        skills[i].level = 10;
                        skills[i].tries = 0;
                        skills[i].percent = 0;
                    }

                    // Restart town
                    setTown(rookTown);
                    loginPosition = getTemplePosition();

                    // Restart first items
                    addStorageValue(30017, 1);

                    // Restart items
                    for (int32_t slot = CONST_SLOT_FIRST; slot <= CONST_SLOT_LAST; slot++)
                    {
                        Item* item = inventory[slot];
                        if (item) {
                            g_game.internalRemoveItem(item, item->getItemCount());
                        }
                    }
                } else {
                    std::cout << "[Warning - Player:death] Rookgaard teletransportation is enabled, rookgaard town does not exist." << std::endl;
                }
            }
        }


in configmanager.cpp:
after:
C:
boolean[PLAYER_CONSOLE_LOGS] = getGlobalBoolean(L, "showPlayerLogInConsole", true);
Paste:
C:
    boolean[GLOBAL_ROOKSYSTEM] = getGlobalBoolean(L, "rookSystem", false); /*Enable rookgaard system*/

after:
C:
    integer[DEPOT_PREMIUM_LIMIT] = getGlobalNumber(L, "depotPremiumLimit", 10000);
Paste:
C:
    integer[ROOKGAARD_TOWN] = getGlobalNumber(L, "rookTown", 1); /*Rook town id */
    integer[ROOKGAARD_LEVEL_THRESHOLD] = getGlobalNumber(L, "levelToRook", 5); /*level to be teleported back to rook */


in configmanager.h:
after:
C:
PLAYER_CONSOLE_LOGS,
Paste:
C:
GLOBAL_ROOKSYSTEM, /*Rooksystem*/

after:
C:
            IP_NUM,
Paste:
C:
            ROOKGAARD_LEVEL_THRESHOLD, /*Level to rook */
            ROOKGAARD_TOWN, /*rookgaard town */


in config.lua, paste:
Lua:
rookSystem = true
rookTown = 1
levelToRook = 5


Compile and test


love you!
@mano368 Players don't get below level 7 don't know why i have nothing related to it in config.lua nor creaturescripts, do you know where else should i look for?
 
Last edited:
love you!
@mano368 Players don't get below level 7 don't know why i have nothing related to it in config.lua nor creaturescripts, do you know where else should i look for?
in player.cpp

search for:
C:
if (vocation->getId() == VOCATION_NONE || level > 7) //dont remember if is 7 or another number
change to:
C:
if (level > 1)
 
in player.cpp

search for:
C:
if (vocation->getId() == VOCATION_NONE || level > 7) //dont remember if is 7 or another number
change to:
C:
if (level > 1)
thank you this is "Buggy" in the clean repository too i checked qwith clean sources and datapack and players can't get below exp 3,906

with your code i get errors in compilation so i changed this
Lua:
if (vocation->getId() == VOCATION_NONE || level > 1)
and players now can get below level 7
and i tested the new rooktown code but it's not working
 

Attachments

thank you this is "Buggy" in the clean repository too i checked qwith clean sources and datapack and players can't get below exp 3,906

with your code i get errors in compilation so i changed this
Lua:
if (vocation->getId() == VOCATION_NONE || level > 1)
and players now can get below level 7
and i tested the new rooktown code but it's not working
your character has a vocation?

show me where you paste the main code
 
show me where you paste the code
player.cpp
Lua:
void Player::death(Creature* lastHitCreature)
{
    loginPosition = town->getTemplePosition();

    if (skillLoss) {
        //uint8_t unfairFightReduction = 100;
        bool lastHitPlayer = Player::lastHitIsPlayer(lastHitCreature);

        /*if (lastHitPlayer) {
            uint32_t sumLevels = 0;
            uint32_t inFightTicks = g_config.getNumber(ConfigManager::PZ_LOCKED);
            for (const auto& it : damageMap) {
                CountBlock_t cb = it.second;
                if ((OTSYS_TIME() - cb.ticks) <= inFightTicks) {
                    Player* damageDealer = g_game.getPlayerByID(it.first);
                    if (damageDealer) {
                        sumLevels += damageDealer->getLevel();
                    }
                }
            }

            if (sumLevels > level) {
                double reduce = level / static_cast<double>(sumLevels);
                unfairFightReduction = std::max<uint8_t>(20, std::floor((reduce * 100) + 0.5));
            }
        }*/

        //Magic level loss
        uint64_t sumMana = 0;
        for (uint32_t i = 1; i <= magLevel; ++i) {
            sumMana += vocation->getReqMana(i);
        }

        //double deathLossPercent = getLostPercent() * (unfairFightReduction / 100.);
        double deathLossPercent = getLostPercent();
        removeManaSpent(static_cast<uint64_t>((sumMana + manaSpent) * deathLossPercent), false);

        //Skill loss
        for (uint8_t i = SKILL_FIRST; i <= SKILL_LAST; ++i) { //for each skill
            uint64_t sumSkillTries = 0;
            for (uint16_t c = MINIMUM_SKILL_LEVEL + 1; c <= skills[i].level; ++c) { //sum up all required tries for all skill levels
                sumSkillTries += vocation->getReqSkillTries(i, c);
            }

            sumSkillTries += skills[i].tries;

            removeSkillTries(static_cast<skills_t>(i), sumSkillTries * deathLossPercent, false);
        }

        //Level loss
        uint64_t expLoss = static_cast<uint64_t>(experience * deathLossPercent);
        g_events->eventPlayerOnLoseExperience(this, expLoss);

        if (expLoss != 0) {
            uint32_t oldLevel = level;

            if (vocation->getId() == VOCATION_NONE || level > 1) { /*Level to rook *//*agregado Enable rookgaard system*/
                experience -= expLoss;
            }

            while (level > 1 && experience < Player::getExpForLevel(level)) {
                --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());
            }

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

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

        if (blessings.test(5)) {
            if (lastHitPlayer) {
                blessings.reset(5);
            } else {
                blessings.reset();
                blessings.set(5);
            }
        } else {
            blessings.reset();
        }

        sendStats();
        sendSkills();
        sendReLoginWindow(0);

        /*if (getSkull() == SKULL_BLACK) {
            health = 40;
            mana = 0;
        } else {
            health = healthMax;
            mana = manaMax;
        }*/

        health = healthMax;
        mana = manaMax;

        auto it = conditions.begin(), end = conditions.end();
        while (it != end) {
            Condition* condition = *it;
            if (condition->isPersistent()) {
                it = conditions.erase(it);

                condition->endCondition(this);
                onEndCondition(condition->getType());
                delete condition;
            } else {
                ++it;
            }
        }
    } else {
        setSkillLoss(true);
        //agregado send player to rook /*agregado Enable rookgaard system*/
           // Teleport players from mainland back to rookgaard
        if (g_config.getBoolean(ConfigManager::GLOBAL_ROOKSYSTEM)) {
            if (vocation->getId() != VOCATION_NONE && level <= static_cast<uint32_t>(g_config.getNumber(ConfigManager::ROOKGAARD_LEVEL_THRESHOLD))) {
                Town* rookTown = g_game.map.towns.getTown(g_config.getNumber(ConfigManager::ROOKGAARD_TOWN));
                if (rookTown) {
                    // Restart stats
                    level = 1;
                    experience = 0;
                    levelPercent = 0;
                    capacity = 40000; //400oz
                    health = 150;
                    healthMax = 150;
                    mana = 0;
                    manaMax = 0;
                    magLevel = 0;
                    magLevelPercent = 0;
                    manaSpent = 0;
                    setVocation(0);

                    // Restart skills
                    for (uint8_t i = SKILL_FIRST; i <= SKILL_LAST; ++i) { //for each skill
                        skills[i].level = 10;
                        skills[i].tries = 0;
                        skills[i].percent = 0;
                    }

                    // Restart town
                    setTown(rookTown);
                    loginPosition = getTemplePosition();

                    // Restart first items
                    addStorageValue(30017, 1);

                    // Restart items
                    for (int32_t slot = CONST_SLOT_FIRST; slot <= CONST_SLOT_LAST; slot++)
                    {
                        Item* item = inventory[slot];
                        if (item) {
                            g_game.internalRemoveItem(item, item->getItemCount());
                        }
                    }
                }
                else {
                    std::cout << "[Warning - Player:death] Rookgaard teletransportation is enabled, rookgaard town does not exist." << std::endl;
                }
            }
        }//agregado send player to sook /*agregado Enable rookgaard system*/

        auto it = conditions.begin(), end = conditions.end();
        while (it != end) {
            Condition* condition = *it;
            if (condition->isPersistent()) {
                it = conditions.erase(it);

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

        health = healthMax;
        g_game.internalTeleport(this, getTemplePosition(), true);
        g_game.addCreatureHealth(this);
        onThink(EVENT_CREATURE_THINK_INTERVAL);
        onIdleStatus();
        sendStats();
    }
}
configmanager.h
Lua:
using ExperienceStages = std::vector<std::tuple<uint32_t, uint32_t, float>>;

class ConfigManager
{
    public:
        ConfigManager();

        enum boolean_config_t {
            ALLOW_CHANGEOUTFIT,
            ONE_PLAYER_ON_ACCOUNT,
            AIMBOT_HOTKEY_ENABLED,
            REMOVE_RUNE_CHARGES,
            REMOVE_WEAPON_AMMO,
            REMOVE_WEAPON_CHARGES,
            REMOVE_POTION_CHARGES,
            PZLOCK_SKULL_ATTACKER,
            EXPERIENCE_FROM_PLAYERS,
            FREE_PREMIUM,
            REPLACE_KICK_ON_LOGIN,
            ALLOW_CLONES,
            ALLOW_WALKTHROUGH,
            BIND_ONLY_GLOBAL_ADDRESS,
            OPTIMIZE_DATABASE,
            MARKET_PREMIUM,
            EMOTE_SPELLS,
            STAMINA_SYSTEM,
            WARN_UNSAFE_SCRIPTS,
            CONVERT_UNSAFE_SCRIPTS,
            CLASSIC_EQUIPMENT_SLOTS,
            CLASSIC_ATTACK_SPEED,
            SCRIPTS_CONSOLE_LOGS,
            SERVER_SAVE_NOTIFY_MESSAGE,
            SERVER_SAVE_CLEAN_MAP,
            SERVER_SAVE_CLOSE,
            SERVER_SAVE_SHUTDOWN,
            ONLINE_OFFLINE_CHARLIST,
            YELL_ALLOW_PREMIUM,
            PREMIUM_TO_SEND_PRIVATE,
            FORCE_MONSTERTYPE_LOAD,
            DEFAULT_WORLD_LIGHT,
            HOUSE_OWNED_BY_ACCOUNT,
            LUA_ITEM_DESC,
            CLEAN_PROTECTION_ZONES,
            HOUSE_DOOR_SHOW_PRICE,
            ONLY_INVITED_CAN_MOVE_HOUSE_ITEMS,
            REMOVE_ON_DESPAWN,
            PLAYER_CONSOLE_LOGS,
            GLOBAL_ROOKSYSTEM, /*Rooksystem*//*agregado Enable rookgaard system*/

            LAST_BOOLEAN_CONFIG /* this must be the last one */
        };

        enum string_config_t {
            MAP_NAME,
            HOUSE_RENT_PERIOD,
            SERVER_NAME,
            OWNER_NAME,
            OWNER_EMAIL,
            URL,
            LOCATION,
            IP,
            MOTD,
            WORLD_TYPE,
            MYSQL_HOST,
            MYSQL_USER,
            MYSQL_PASS,
            MYSQL_DB,
            MYSQL_SOCK,
            DEFAULT_PRIORITY,
            MAP_AUTHOR,
            CONFIG_FILE,

            LAST_STRING_CONFIG /* this must be the last one */
        };

        enum integer_config_t {
            SQL_PORT,
            MAX_PLAYERS,
            PZ_LOCKED,
            DEFAULT_DESPAWNRANGE,
            DEFAULT_DESPAWNRADIUS,
            DEFAULT_WALKTOSPAWNRADIUS,
            RATE_EXPERIENCE,
            RATE_SKILL,
            RATE_LOOT,
            RATE_MAGIC,
            RATE_SPAWN,
            HOUSE_PRICE,
            KILLS_TO_RED,
            KILLS_TO_BLACK,
            MAX_MESSAGEBUFFER,
            ACTIONS_DELAY_INTERVAL,
            EX_ACTIONS_DELAY_INTERVAL,
            KICK_AFTER_MINUTES,
            PROTECTION_LEVEL,
            DEATH_LOSE_PERCENT,
            STATUSQUERY_TIMEOUT,
            FRAG_TIME,
            WHITE_SKULL_TIME,
            GAME_PORT,
            LOGIN_PORT,
            STATUS_PORT,
            STAIRHOP_DELAY,
            MARKET_OFFER_DURATION,
            CHECK_EXPIRED_MARKET_OFFERS_EACH_MINUTES,
            MAX_MARKET_OFFERS_AT_A_TIME_PER_PLAYER,
            EXP_FROM_PLAYERS_LEVEL_RANGE,
            MAX_PACKETS_PER_SECOND,
            SERVER_SAVE_NOTIFY_DURATION,
            YELL_MINIMUM_LEVEL,
            MINIMUM_LEVEL_TO_SEND_PRIVATE,
            VIP_FREE_LIMIT,
            VIP_PREMIUM_LIMIT,
            DEPOT_FREE_LIMIT,
            DEPOT_PREMIUM_LIMIT,
            IP_NUM,
            ROOKGAARD_LEVEL_THRESHOLD, /*Level to rook *//*agregado Enable rookgaard system*/
            ROOKGAARD_TOWN, /*rookgaard town *//*agregado Enable rookgaard system*/

            LAST_INTEGER_CONFIG /* this must be the last one */
        };
configmanager.cpp
Code:
    boolean[ALLOW_CHANGEOUTFIT] = getGlobalBoolean(L, "allowChangeOutfit", true);
    boolean[ONE_PLAYER_ON_ACCOUNT] = getGlobalBoolean(L, "onePlayerOnlinePerAccount", true);
    boolean[AIMBOT_HOTKEY_ENABLED] = getGlobalBoolean(L, "hotkeyAimbotEnabled", true);
    boolean[REMOVE_RUNE_CHARGES] = getGlobalBoolean(L, "removeChargesFromRunes", true);
    boolean[REMOVE_WEAPON_AMMO] = getGlobalBoolean(L, "removeWeaponAmmunition", true);
    boolean[REMOVE_WEAPON_CHARGES] = getGlobalBoolean(L, "removeWeaponCharges", true);
    boolean[REMOVE_POTION_CHARGES] = getGlobalBoolean(L, "removeChargesFromPotions", true);
    boolean[PZLOCK_SKULL_ATTACKER] = getGlobalBoolean(L, "pzLockSkullAttacker", false);

    boolean[EXPERIENCE_FROM_PLAYERS] = getGlobalBoolean(L, "experienceByKillingPlayers", false);
    boolean[FREE_PREMIUM] = getGlobalBoolean(L, "freePremium", false);
    boolean[REPLACE_KICK_ON_LOGIN] = getGlobalBoolean(L, "replaceKickOnLogin", true);
    boolean[ALLOW_CLONES] = getGlobalBoolean(L, "allowClones", false);
    boolean[ALLOW_WALKTHROUGH] = getGlobalBoolean(L, "allowWalkthrough", true);
    boolean[MARKET_PREMIUM] = getGlobalBoolean(L, "premiumToCreateMarketOffer", true);
    boolean[EMOTE_SPELLS] = getGlobalBoolean(L, "emoteSpells", false);
    boolean[STAMINA_SYSTEM] = getGlobalBoolean(L, "staminaSystem", true);
    boolean[WARN_UNSAFE_SCRIPTS] = getGlobalBoolean(L, "warnUnsafeScripts", true);
    boolean[CONVERT_UNSAFE_SCRIPTS] = getGlobalBoolean(L, "convertUnsafeScripts", true);
    boolean[CLASSIC_EQUIPMENT_SLOTS] = getGlobalBoolean(L, "classicEquipmentSlots", false);
    boolean[CLASSIC_ATTACK_SPEED] = getGlobalBoolean(L, "classicAttackSpeed", false);
    boolean[SCRIPTS_CONSOLE_LOGS] = getGlobalBoolean(L, "showScriptsLogInConsole", true);
    boolean[SERVER_SAVE_NOTIFY_MESSAGE] = getGlobalBoolean(L, "serverSaveNotifyMessage", true);
    boolean[SERVER_SAVE_CLEAN_MAP] = getGlobalBoolean(L, "serverSaveCleanMap", false);
    boolean[SERVER_SAVE_CLOSE] = getGlobalBoolean(L, "serverSaveClose", false);
    boolean[SERVER_SAVE_SHUTDOWN] = getGlobalBoolean(L, "serverSaveShutdown", true);
    boolean[ONLINE_OFFLINE_CHARLIST] = getGlobalBoolean(L, "showOnlineStatusInCharlist", false);
    boolean[YELL_ALLOW_PREMIUM] = getGlobalBoolean(L, "yellAlwaysAllowPremium", false);
    boolean[PREMIUM_TO_SEND_PRIVATE] = getGlobalBoolean(L, "premiumToSendPrivate", false);
    boolean[FORCE_MONSTERTYPE_LOAD] = getGlobalBoolean(L, "forceMonsterTypesOnLoad", true);
    boolean[DEFAULT_WORLD_LIGHT] = getGlobalBoolean(L, "defaultWorldLight", true);
    boolean[HOUSE_OWNED_BY_ACCOUNT] = getGlobalBoolean(L, "houseOwnedByAccount", false);
    boolean[LUA_ITEM_DESC] = getGlobalBoolean(L, "luaItemDesc", false);
    boolean[CLEAN_PROTECTION_ZONES] = getGlobalBoolean(L, "cleanProtectionZones", false);
    boolean[HOUSE_DOOR_SHOW_PRICE] = getGlobalBoolean(L, "houseDoorShowPrice", true);
    boolean[ONLY_INVITED_CAN_MOVE_HOUSE_ITEMS] = getGlobalBoolean(L, "onlyInvitedCanMoveHouseItems", true);
    boolean[REMOVE_ON_DESPAWN] = getGlobalBoolean(L, "removeOnDespawn", true);
    boolean[PLAYER_CONSOLE_LOGS] = getGlobalBoolean(L, "showPlayerLogInConsole", true);
    boolean[GLOBAL_ROOKSYSTEM] = getGlobalBoolean(L, "rookSystem", true); /*agregado Enable rookgaard system*/

    string[DEFAULT_PRIORITY] = getGlobalString(L, "defaultPriority", "high");
    string[SERVER_NAME] = getGlobalString(L, "serverName", "");
    string[OWNER_NAME] = getGlobalString(L, "ownerName", "");
    string[OWNER_EMAIL] = getGlobalString(L, "ownerEmail", "");
    string[URL] = getGlobalString(L, "url", "");
    string[LOCATION] = getGlobalString(L, "location", "");
    string[MOTD] = getGlobalString(L, "motd", "");
    string[WORLD_TYPE] = getGlobalString(L, "worldType", "pvp");

    integer[MAX_PLAYERS] = getGlobalNumber(L, "maxPlayers");
    integer[PZ_LOCKED] = getGlobalNumber(L, "pzLocked", 60000);
    integer[DEFAULT_DESPAWNRANGE] = Monster::despawnRange = getGlobalNumber(L, "deSpawnRange", 2);
    integer[DEFAULT_DESPAWNRADIUS] = Monster::despawnRadius = getGlobalNumber(L, "deSpawnRadius", 50);
    integer[DEFAULT_WALKTOSPAWNRADIUS] = getGlobalNumber(L, "walkToSpawnRadius", 15);
    integer[RATE_EXPERIENCE] = getGlobalNumber(L, "rateExp", 5);
    integer[RATE_SKILL] = getGlobalNumber(L, "rateSkill", 3);
    integer[RATE_LOOT] = getGlobalNumber(L, "rateLoot", 2);
    integer[RATE_MAGIC] = getGlobalNumber(L, "rateMagic", 3);
    integer[RATE_SPAWN] = getGlobalNumber(L, "rateSpawn", 1);
    integer[HOUSE_PRICE] = getGlobalNumber(L, "housePriceEachSQM", 1000);
    integer[KILLS_TO_RED] = getGlobalNumber(L, "killsToRedSkull", 3);
    integer[KILLS_TO_BLACK] = getGlobalNumber(L, "killsToBlackSkull", 6);
    integer[ACTIONS_DELAY_INTERVAL] = getGlobalNumber(L, "timeBetweenActions", 200);
    integer[EX_ACTIONS_DELAY_INTERVAL] = getGlobalNumber(L, "timeBetweenExActions", 1000);
    integer[MAX_MESSAGEBUFFER] = getGlobalNumber(L, "maxMessageBuffer", 4);
    integer[KICK_AFTER_MINUTES] = getGlobalNumber(L, "kickIdlePlayerAfterMinutes", 15);
    integer[PROTECTION_LEVEL] = getGlobalNumber(L, "protectionLevel", 1);
    integer[DEATH_LOSE_PERCENT] = getGlobalNumber(L, "deathLosePercent", -1);
    integer[STATUSQUERY_TIMEOUT] = getGlobalNumber(L, "statusTimeout", 5000);
    integer[FRAG_TIME] = getGlobalNumber(L, "timeToDecreaseFrags", 24 * 60 * 60);
    integer[WHITE_SKULL_TIME] = getGlobalNumber(L, "whiteSkullTime", 15 * 60);
    integer[STAIRHOP_DELAY] = getGlobalNumber(L, "stairJumpExhaustion", 2000);
    integer[EXP_FROM_PLAYERS_LEVEL_RANGE] = getGlobalNumber(L, "expFromPlayersLevelRange", 75);
    integer[CHECK_EXPIRED_MARKET_OFFERS_EACH_MINUTES] = getGlobalNumber(L, "checkExpiredMarketOffersEachMinutes", 60);
    integer[MAX_MARKET_OFFERS_AT_A_TIME_PER_PLAYER] = getGlobalNumber(L, "maxMarketOffersAtATimePerPlayer", 100);
    integer[MAX_PACKETS_PER_SECOND] = getGlobalNumber(L, "maxPacketsPerSecond", 25);
    integer[SERVER_SAVE_NOTIFY_DURATION] = getGlobalNumber(L, "serverSaveNotifyDuration", 5);
    integer[YELL_MINIMUM_LEVEL] = getGlobalNumber(L, "yellMinimumLevel", 2);
    integer[MINIMUM_LEVEL_TO_SEND_PRIVATE] = getGlobalNumber(L, "minimumLevelToSendPrivate", 1);
    integer[VIP_FREE_LIMIT] = getGlobalNumber(L, "vipFreeLimit", 20);
    integer[VIP_PREMIUM_LIMIT] = getGlobalNumber(L, "vipPremiumLimit", 100);
    integer[DEPOT_FREE_LIMIT] = getGlobalNumber(L, "depotFreeLimit", 2000);
    integer[DEPOT_PREMIUM_LIMIT] = getGlobalNumber(L, "depotPremiumLimit", 10000);
    integer[ROOKGAARD_TOWN] = getGlobalNumber(L, "rookTown", 1); /*Rook town id *//*agregado Enable rookgaard system*/
    integer[ROOKGAARD_LEVEL_THRESHOLD] = getGlobalNumber(L, "levelToRook", 5); /*level to be teleported back to rook *//*agregado Enable rookgaard system*/

    expStages = loadXMLStages();

config.lua
Code:
--agregado rook system
rookSystem = true
rookTown = 1
levelToRook = 5
-- Connection Config

just in case luascript.cpp
Code:
    // configKeys
    registerTable("configKeys");
    /*agregado Enable rookgaard system*/
    registerEnumIn("configKeys", ConfigManager::GLOBAL_ROOKSYSTEM)
    registerEnumIn("configKeys", ConfigManager::ROOKGAARD_LEVEL_THRESHOLD)
    registerEnumIn("configKeys", ConfigManager::ROOKGAARD_TOWN)
        /*agregado Enable rookgaard system*/
    registerEnumIn("configKeys", ConfigManager::ALLOW_CHANGEOUTFIT)
 
player.cpp

player.cpp only

C:
void Player::death(Creature* lastHitCreature)
{
    loginPosition = town->getTemplePosition();

    if (skillLoss) {
        //uint8_t unfairFightReduction = 100;
        bool lastHitPlayer = Player::lastHitIsPlayer(lastHitCreature);

        /*if (lastHitPlayer) {
            uint32_t sumLevels = 0;
            uint32_t inFightTicks = g_config.getNumber(ConfigManager::PZ_LOCKED);
            for (const auto& it : damageMap) {
                CountBlock_t cb = it.second;
                if ((OTSYS_TIME() - cb.ticks) <= inFightTicks) {
                    Player* damageDealer = g_game.getPlayerByID(it.first);
                    if (damageDealer) {
                        sumLevels += damageDealer->getLevel();
                    }
                }
            }

            if (sumLevels > level) {
                double reduce = level / static_cast<double>(sumLevels);
                unfairFightReduction = std::max<uint8_t>(20, std::floor((reduce * 100) + 0.5));
            }
        }*/

        //Magic level loss
        uint64_t sumMana = 0;
        for (uint32_t i = 1; i <= magLevel; ++i) {
            sumMana += vocation->getReqMana(i);
        }

        //double deathLossPercent = getLostPercent() * (unfairFightReduction / 100.);
        double deathLossPercent = getLostPercent();
        removeManaSpent(static_cast<uint64_t>((sumMana + manaSpent) * deathLossPercent), false);

        //Skill loss
        for (uint8_t i = SKILL_FIRST; i <= SKILL_LAST; ++i) { //for each skill
            uint64_t sumSkillTries = 0;
            for (uint16_t c = MINIMUM_SKILL_LEVEL + 1; c <= skills[i].level; ++c) { //sum up all required tries for all skill levels
                sumSkillTries += vocation->getReqSkillTries(i, c);
            }

            sumSkillTries += skills[i].tries;

            removeSkillTries(static_cast<skills_t>(i), sumSkillTries * deathLossPercent, false);
        }

        //Level loss
        uint64_t expLoss = static_cast<uint64_t>(experience * deathLossPercent);
        g_events->eventPlayerOnLoseExperience(this, expLoss);

        if (expLoss != 0) {
            uint32_t oldLevel = level;

            if (vocation->getId() == VOCATION_NONE || level > 1) { /*Level to rook *//*agregado Enable rookgaard system*/
                experience -= expLoss;
            }

            while (level > 1 && experience < Player::getExpForLevel(level)) {
                --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());
            }

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

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

        if (blessings.test(5)) {
            if (lastHitPlayer) {
                blessings.reset(5);
            } else {
                blessings.reset();
                blessings.set(5);
            }
        } else {
            blessings.reset();
        }

        sendStats();
        sendSkills();
        sendReLoginWindow(0);

        /*if (getSkull() == SKULL_BLACK) {
            health = 40;
            mana = 0;
        } else {
            health = healthMax;
            mana = manaMax;
        }*/

        health = healthMax;
        mana = manaMax;

        auto it = conditions.begin(), end = conditions.end();
        while (it != end) {
            Condition* condition = *it;
            if (condition->isPersistent()) {
                it = conditions.erase(it);

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

        //agregado send player to rook /*agregado Enable rookgaard system*/
           // Teleport players from mainland back to rookgaard
        if (g_config.getBoolean(ConfigManager::GLOBAL_ROOKSYSTEM)) {
            if (vocation->getId() != VOCATION_NONE && level <= static_cast<uint32_t>(g_config.getNumber(ConfigManager::ROOKGAARD_LEVEL_THRESHOLD))) {
                Town* rookTown = g_game.map.towns.getTown(g_config.getNumber(ConfigManager::ROOKGAARD_TOWN));
                if (rookTown) {
                    // Restart stats
                    level = 1;
                    experience = 0;
                    levelPercent = 0;
                    capacity = 40000; //400oz
                    health = 150;
                    healthMax = 150;
                    mana = 0;
                    manaMax = 0;
                    magLevel = 0;
                    magLevelPercent = 0;
                    manaSpent = 0;
                    setVocation(0);

                    // Restart skills
                    for (uint8_t i = SKILL_FIRST; i <= SKILL_LAST; ++i) { //for each skill
                        skills[i].level = 10;
                        skills[i].tries = 0;
                        skills[i].percent = 0;
                    }

                    // Restart town
                    setTown(rookTown);
                    loginPosition = getTemplePosition();

                    // Restart first items
                    addStorageValue(30017, 1);

                    // Restart items
                    for (int32_t slot = CONST_SLOT_FIRST; slot <= CONST_SLOT_LAST; slot++)
                    {
                        Item* item = inventory[slot];
                        if (item) {
                            g_game.internalRemoveItem(item, item->getItemCount());
                        }
                    }
                }
                else {
                    std::cout << "[Warning - Player:death] Rookgaard teletransportation is enabled, rookgaard town does not exist." << std::endl;
                }
            }
        }//agregado send player to sook /*agregado Enable rookgaard system*/

    } else {
        setSkillLoss(true);

        auto it = conditions.begin(), end = conditions.end();
        while (it != end) {
            Condition* condition = *it;
            if (condition->isPersistent()) {
                it = conditions.erase(it);

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

        health = healthMax;
        g_game.internalTeleport(this, getTemplePosition(), true);
        g_game.addCreatureHealth(this);
        onThink(EVENT_CREATURE_THINK_INTERVAL);
        onIdleStatus();
        sendStats();
    }
}
 
player.cpp only

C:
void Player::death(Creature* lastHitCreature)
{
    loginPosition = town->getTemplePosition();

    if (skillLoss) {
        //uint8_t unfairFightReduction = 100;
        bool lastHitPlayer = Player::lastHitIsPlayer(lastHitCreature);

        /*if (lastHitPlayer) {
            uint32_t sumLevels = 0;
            uint32_t inFightTicks = g_config.getNumber(ConfigManager::PZ_LOCKED);
            for (const auto& it : damageMap) {
                CountBlock_t cb = it.second;
                if ((OTSYS_TIME() - cb.ticks) <= inFightTicks) {
                    Player* damageDealer = g_game.getPlayerByID(it.first);
                    if (damageDealer) {
                        sumLevels += damageDealer->getLevel();
                    }
                }
            }

            if (sumLevels > level) {
                double reduce = level / static_cast<double>(sumLevels);
                unfairFightReduction = std::max<uint8_t>(20, std::floor((reduce * 100) + 0.5));
            }
        }*/

        //Magic level loss
        uint64_t sumMana = 0;
        for (uint32_t i = 1; i <= magLevel; ++i) {
            sumMana += vocation->getReqMana(i);
        }

        //double deathLossPercent = getLostPercent() * (unfairFightReduction / 100.);
        double deathLossPercent = getLostPercent();
        removeManaSpent(static_cast<uint64_t>((sumMana + manaSpent) * deathLossPercent), false);

        //Skill loss
        for (uint8_t i = SKILL_FIRST; i <= SKILL_LAST; ++i) { //for each skill
            uint64_t sumSkillTries = 0;
            for (uint16_t c = MINIMUM_SKILL_LEVEL + 1; c <= skills[i].level; ++c) { //sum up all required tries for all skill levels
                sumSkillTries += vocation->getReqSkillTries(i, c);
            }

            sumSkillTries += skills[i].tries;

            removeSkillTries(static_cast<skills_t>(i), sumSkillTries * deathLossPercent, false);
        }

        //Level loss
        uint64_t expLoss = static_cast<uint64_t>(experience * deathLossPercent);
        g_events->eventPlayerOnLoseExperience(this, expLoss);

        if (expLoss != 0) {
            uint32_t oldLevel = level;

            if (vocation->getId() == VOCATION_NONE || level > 1) { /*Level to rook *//*agregado Enable rookgaard system*/
                experience -= expLoss;
            }

            while (level > 1 && experience < Player::getExpForLevel(level)) {
                --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());
            }

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

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

        if (blessings.test(5)) {
            if (lastHitPlayer) {
                blessings.reset(5);
            } else {
                blessings.reset();
                blessings.set(5);
            }
        } else {
            blessings.reset();
        }

        sendStats();
        sendSkills();
        sendReLoginWindow(0);

        /*if (getSkull() == SKULL_BLACK) {
            health = 40;
            mana = 0;
        } else {
            health = healthMax;
            mana = manaMax;
        }*/

        health = healthMax;
        mana = manaMax;

        auto it = conditions.begin(), end = conditions.end();
        while (it != end) {
            Condition* condition = *it;
            if (condition->isPersistent()) {
                it = conditions.erase(it);

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

        //agregado send player to rook /*agregado Enable rookgaard system*/
           // Teleport players from mainland back to rookgaard
        if (g_config.getBoolean(ConfigManager::GLOBAL_ROOKSYSTEM)) {
            if (vocation->getId() != VOCATION_NONE && level <= static_cast<uint32_t>(g_config.getNumber(ConfigManager::ROOKGAARD_LEVEL_THRESHOLD))) {
                Town* rookTown = g_game.map.towns.getTown(g_config.getNumber(ConfigManager::ROOKGAARD_TOWN));
                if (rookTown) {
                    // Restart stats
                    level = 1;
                    experience = 0;
                    levelPercent = 0;
                    capacity = 40000; //400oz
                    health = 150;
                    healthMax = 150;
                    mana = 0;
                    manaMax = 0;
                    magLevel = 0;
                    magLevelPercent = 0;
                    manaSpent = 0;
                    setVocation(0);

                    // Restart skills
                    for (uint8_t i = SKILL_FIRST; i <= SKILL_LAST; ++i) { //for each skill
                        skills[i].level = 10;
                        skills[i].tries = 0;
                        skills[i].percent = 0;
                    }

                    // Restart town
                    setTown(rookTown);
                    loginPosition = getTemplePosition();

                    // Restart first items
                    addStorageValue(30017, 1);

                    // Restart items
                    for (int32_t slot = CONST_SLOT_FIRST; slot <= CONST_SLOT_LAST; slot++)
                    {
                        Item* item = inventory[slot];
                        if (item) {
                            g_game.internalRemoveItem(item, item->getItemCount());
                        }
                    }
                }
                else {
                    std::cout << "[Warning - Player:death] Rookgaard teletransportation is enabled, rookgaard town does not exist." << std::endl;
                }
            }
        }//agregado send player to sook /*agregado Enable rookgaard system*/

    } else {
        setSkillLoss(true);

        auto it = conditions.begin(), end = conditions.end();
        while (it != end) {
            Condition* condition = *it;
            if (condition->isPersistent()) {
                it = conditions.erase(it);

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

        health = healthMax;
        g_game.internalTeleport(this, getTemplePosition(), true);
        g_game.addCreatureHealth(this);
        onThink(EVENT_CREATURE_THINK_INTERVAL);
        onIdleStatus();
        sendStats();
    }
}
it's working i forgot to change the twonid it wasn't sending errors in console hahaha. thank you!
@mano368
 

Attachments

Last edited:
it's working i forgot to change the twonid it wasn't sending errors in console hahaha. thank you!
@mano368
after compiled again? because you paste the code in the wrong location, so, if the code works like that im surprise hahaha

have fun bro

@Diarreamental
a fix, to give the player first items again

in firstitems.lua in creaturescripts.
where is:
Lua:
    if player:getLastLoginSaved() == 0 then

change to:
Lua:
    if player:getLastLoginSaved() == 0 or player:getStorageValue(30017) == 1 then
        player:setStorageValue(30017, 0) -- reset storage for first items
 
after compiled again? because you paste the code in the wrong location, so, if the code works like that im surprise hahaha

have fun bro

@Diarreamental
a fix, to give the player first items again

in firstitems.lua in creaturescripts.
where is:
Lua:
    if player:getLastLoginSaved() == 0 then

change to:
Lua:
    if player:getLastLoginSaved() == 0 or player:getStorageValue(30017) == 1 then
        player:setStorageValue(30017, 0) -- reset storage for first items
Thank you !
yes i recompiled again, copied your whole code and delete the one that i added from tip to toe
 
You can try with this:

data/scripts/onlosspremium.lua
Lua:
local storage = 88888
local defaultCity = "Thais"

local creatureEvent = CreatureEvent("onLossPremium")

function creatureEvent.onLogin(player)
    if player:getStorageValue(storage) == -1 then
        player:setStorageValue(storage, player:isPremium() and 1 or 0)
    end
    if player:getPremiumEndsAt() < os.time() then
        if player:getStorageValue(storage) == 1 then
            player:setStorageValue(storage, 0)
            player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Your premium time has expired.")
            local thais = Town(defaultCity)
            player:setTown(thais)
            local thaisPos = thais:getTemplePosition()
            player:teleportTo(thaisPos)
            thaisPos:sendMagicEffect(CONST_ME_TELEPORT)
        end
    elseif player:getStorageValue(storage) == 0 then
        player:setStorageValue(storage, 1)
    end
    return true
end

creatureEvent:register()
@Sarah Wesker would be possible to add remove house on loss premium + send items to free zone depot please?
 
thank you. And how to send item from premium zone to the teleport free zone? or is it not possible?
When player lose house, items will be sent to deppot.
I think its possible to send to free area, but need to made sources edit


You can do a check, for house town id, if townid is different from free town id, send player items to a specific townid, like Thais or another
 
Last edited:
Back
Top