• 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!
  • 2026 staff recruitment is open! Check it out and consider applying!

Lua Loot/Spawn rate as floating point numbers

thomson9292

New Member
Joined
Feb 28, 2017
Messages
97
Solutions
1
Reaction score
2
Is it possible to set in config.lua drop and respawn rate as floating point numbers? When loot rate is set to "2" chance for good loot is too high but when it's set to "1" chance is to low. I tried to type "1.5" but I doubt that it works. Should I try to use dot or comma? Or maybe in this file I can use only intiger?
 
Solution
Floating point loot rate for config.lua · Vulcanx/forgottenserver@ecc7a9f · GitHub
see if this works
i was trying to add spawn rate too but it looks like it would be incompatible with a float since it compares spawn count with an integer in spawn.cpp (and spawn count should stay an integer, you can't have 0.xx of a monster)
also change
C++:
float getGlobalFloat(lua_State* L, const char* identifier, const bool defaultValue = 0.0)
to
C++:
float getGlobalFloat(lua_State* L, const char* identifier, const float defaultValue = 0.0)

i forgot to change bool to float and (im too lazy to fix it and put everything into 1 commit again)
Can't I change drop and respawn rate in config.lua (in main ots file)?
Did you test it?

Edit:
Loot rate should be possible i think since its a % value i might be wrong tho
not sure about spawn rate

I also saw that you did test it.
but 1.5 will make an item that has 50% drop rate increas by 25% so the new drop value would be 75%

Edit2:
i did have a look inside my source (0.3.6) and seems to be a double so you should be able to set drop rate to 1.5 in config.lua
I guess newer TFS also use it as an double/float
 
Last edited:
I know I can change it to intiger. When I type "2" or "1" it works. But I think 1.5 works same as 1. I'm not sure it is possible to use floating point numbers in this file, or I should put comma instead of dot.
 
I know I can change it to intiger. When I type "2" or "1" it works. But I think 1.5 works same as 1. I'm not sure it is possible to use floating point numbers in this file, or I should put comma instead of dot.
What version of tfs are you using?
because in 0.3.6 you can use 1.5

code from monster.cpp
Code:
uint16_t Monsters::getLootRandom()
{
   return (uint16_t)std::ceil((double)random_range(0, MAX_LOOTCHANCE) / g_config.getDouble(ConfigManager::RATE_LOOT));
}

Edit:
monster spawn seems to be an integer
 
I use tfs 1.2. So can't I use values between 1 and 2?
This is how it looks like in tfs 1.2

Code:
uint32_t Monsters::getLootRandom()
{
return uniform_random(0, MAX_LOOTCHANCE) / g_config.getNumber(ConfigManager::RATE_LOOT);
}

seems like it return an int, im not sure. i have to look more inside the source else you can always edit the source, to make it possible to use a float/double value.

Edit:
tfs 1.2 loot rate is an integer so you cant set lootrate to 1.5

configmanager.cpp
Code:
integer[RATE_LOOT] = getGlobalNumber(L, "rateLoot", 2);

So you have to edit the monster files, or edit the source files.
 
Last edited:
I would rather make changes in config.lua than in each monster file. Can anyone point me in which files I can make changes for loot and respawn rate?

If I declare float variable instead of int will it make any problem with my server? Will this change be enough to make floating point numbers work in config.lua?
 
I would rather make changes in config.lua than in each monster file. Can anyone point me in which files I can make changes for loot and respawn rate?

If I declare float variable instead of int will it make any problem with my server? Will this change be enough to make floating point numbers work in config.lua?
Im not sure about that, im not experienced enought whit c++ so im not the right person to ask.
 
Floating point loot rate for config.lua · Vulcanx/forgottenserver@ecc7a9f · GitHub
see if this works
i was trying to add spawn rate too but it looks like it would be incompatible with a float since it compares spawn count with an integer in spawn.cpp (and spawn count should stay an integer, you can't have 0.xx of a monster)
also change
C++:
float getGlobalFloat(lua_State* L, const char* identifier, const bool defaultValue = 0.0)
to
C++:
float getGlobalFloat(lua_State* L, const char* identifier, const float defaultValue = 0.0)

i forgot to change bool to float and (im too lazy to fix it and put everything into 1 commit again)
 
Solution
My code looks a bit different (I think this one in your link is from another tfs version)
I Hope I added a new lines of code in a correct place. I will check if it's work in the moment.

Code:
#include "otpch.h"

#include "configmanager.h"
#include "game.h"

#if LUA_VERSION_NUM >= 502
#undef lua_strlen
#define lua_strlen lua_rawlen
#endif

extern Game g_game;

bool ConfigManager::load()
{
    lua_State* L = luaL_newstate();
    if (!L) {
        throw std::runtime_error("Failed to allocate memory");
    }

    luaL_openlibs(L);

    if (luaL_dofile(L, "config.lua")) {
        std::cout << "[Error - ConfigManager::load] " << lua_tostring(L, -1) << std::endl;
        lua_close(L);
        return false;
    }

    //parse config
    if (!loaded) { //info that must be loaded one time (unless we reset the modules involved)
        boolean[BIND_ONLY_GLOBAL_ADDRESS] = getGlobalBoolean(L, "bindOnlyGlobalAddress", false);
        boolean[OPTIMIZE_DATABASE] = getGlobalBoolean(L, "startupDatabaseOptimization", true);

        string[IP] = getGlobalString(L, "ip", "127.0.0.1");
        string[MAP_NAME] = getGlobalString(L, "mapName", "forgotten");
        string[MAP_AUTHOR] = getGlobalString(L, "mapAuthor", "Unknown");
        string[HOUSE_RENT_PERIOD] = getGlobalString(L, "houseRentPeriod", "never");
        string[MYSQL_HOST] = getGlobalString(L, "mysqlHost", "127.0.0.1");
        string[MYSQL_USER] = getGlobalString(L, "mysqlUser", "forgottenserver");
        string[MYSQL_PASS] = getGlobalString(L, "mysqlPass", "");
        string[MYSQL_DB] = getGlobalString(L, "mysqlDatabase", "forgottenserver");
        string[MYSQL_SOCK] = getGlobalString(L, "mysqlSock", "");

        integer[SQL_PORT] = getGlobalNumber(L, "mysqlPort", 3306);
        integer[GAME_PORT] = getGlobalNumber(L, "gameProtocolPort", 7172);
        integer[LOGIN_PORT] = getGlobalNumber(L, "loginProtocolPort", 7171);
        integer[STATUS_PORT] = getGlobalNumber(L, "statusProtocolPort", 7171);

        integer[MARKET_OFFER_DURATION] = getGlobalNumber(L, "marketOfferDuration", 30 * 24 * 60 * 60);
    }

    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[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[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);

    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] = getGlobalNumber(L, "deSpawnRange", 2);
    integer[DEFAULT_DESPAWNRADIUS] = getGlobalNumber(L, "deSpawnRadius", 50);
    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 * 1000);
    integer[WHITE_SKULL_TIME] = getGlobalNumber(L, "whiteSkullTime", 15 * 60 * 1000);
    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);


    // floating loot (added)
    floating[RATE_LOOT] = getGlobalFloat(L, "rateLoot", 2.0);

    loaded = true;
    lua_close(L);
    return true;
}

bool ConfigManager::reload()
{
    bool result = load();
    if (transformToSHA1(getString(ConfigManager::MOTD)) != g_game.getMotdHash()) {
        g_game.incrementMotdNum();
    }
    return result;
}

const std::string& ConfigManager::getString(string_config_t what) const
{
    if (what >= LAST_STRING_CONFIG) {
        std::cout << "[Warning - ConfigManager::getString] Accessing invalid index: " << what << std::endl;
        return string[DUMMY_STR];
    }
    return string[what];
}

int32_t ConfigManager::getNumber(integer_config_t what) const
{
    if (what >= LAST_INTEGER_CONFIG) {
        std::cout << "[Warning - ConfigManager::getNumber] Accessing invalid index: " << what << std::endl;
        return 0;
    }
    return integer[what];
}

bool ConfigManager::getBoolean(boolean_config_t what) const
{
    if (what >= LAST_BOOLEAN_CONFIG) {
        std::cout << "[Warning - ConfigManager::getBoolean] Accessing invalid index: " << what << std::endl;
        return false;
    }
    return boolean[what];
}

std::string ConfigManager::getGlobalString(lua_State* L, const char* identifier, const char* defaultValue)
{
    lua_getglobal(L, identifier);
    if (!lua_isstring(L, -1)) {
        return defaultValue;
    }

    size_t len = lua_strlen(L, -1);
    std::string ret(lua_tostring(L, -1), len);
    lua_pop(L, 1);
    return ret;
}

int32_t ConfigManager::getGlobalNumber(lua_State* L, const char* identifier, const int32_t defaultValue)
{
    lua_getglobal(L, identifier);
    if (!lua_isnumber(L, -1)) {
        return defaultValue;
    }

    int32_t val = lua_tonumber(L, -1);
    lua_pop(L, 1);
    return val;
}

bool ConfigManager::getGlobalBoolean(lua_State* L, const char* identifier, const bool defaultValue)
{
    lua_getglobal(L, identifier);
    if (!lua_isboolean(L, -1)) {
        if (!lua_isstring(L, -1)) {
            return defaultValue;
        }

        size_t len = lua_strlen(L, -1);
        std::string ret(lua_tostring(L, -1), len);
        lua_pop(L, 1);
        return booleanString(ret);
    }

    int val = lua_toboolean(L, -1);
    lua_pop(L, 1);
    return val != 0;
}


// floating loot (added)
float getGlobalFloat(lua_State* L, const char* identifier, const float defaultValue = 0.0)
{
    lua_getglobal(L, identifier);
    if (!lua_isnumber(L, -1)) {
        return defaultValue;

    }

    float val = lua_tonumber(L, -1);
    lua_pop(L, 1);
    return val;
}

// floating loot (added)
float ConfigManager::getFloat(floating_config_t what) const
{
    if (what >= LAST_FLOATING_CONFIG) {
        std::cout << "[Warning - ConfigManager::getFLoat] Accessing invalid index: " << what << std::endl;
        return 0;
    
    }
    return floating[what];
}

EDIT.

Unfortunately I got an error during compiling.

8xjLLKq.png


Code:
/**
 * The Forgotten Server - a free and open-source MMORPG server emulator
 * Copyright (C) 2016  Mark Samman <[email protected]>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include "otpch.h"

#include "configmanager.h"
#include "game.h"

#if LUA_VERSION_NUM >= 502
#undef lua_strlen
#define lua_strlen lua_rawlen
#endif

extern Game g_game;

bool ConfigManager::load()
{
    lua_State* L = luaL_newstate();
    if (!L) {
        throw std::runtime_error("Failed to allocate memory");
    }

    luaL_openlibs(L);

    if (luaL_dofile(L, "config.lua")) {
        std::cout << "[Error - ConfigManager::load] " << lua_tostring(L, -1) << std::endl;
        lua_close(L);
        return false;
    }

    //parse config
    if (!loaded) { //info that must be loaded one time (unless we reset the modules involved)
        boolean[BIND_ONLY_GLOBAL_ADDRESS] = getGlobalBoolean(L, "bindOnlyGlobalAddress", false);
        boolean[OPTIMIZE_DATABASE] = getGlobalBoolean(L, "startupDatabaseOptimization", true);

        string[IP] = getGlobalString(L, "ip", "127.0.0.1");
        string[MAP_NAME] = getGlobalString(L, "mapName", "forgotten");
        string[MAP_AUTHOR] = getGlobalString(L, "mapAuthor", "Unknown");
        string[HOUSE_RENT_PERIOD] = getGlobalString(L, "houseRentPeriod", "never");
        string[MYSQL_HOST] = getGlobalString(L, "mysqlHost", "127.0.0.1");
        string[MYSQL_USER] = getGlobalString(L, "mysqlUser", "forgottenserver");
        string[MYSQL_PASS] = getGlobalString(L, "mysqlPass", "");
        string[MYSQL_DB] = getGlobalString(L, "mysqlDatabase", "forgottenserver");
        string[MYSQL_SOCK] = getGlobalString(L, "mysqlSock", "");

        integer[SQL_PORT] = getGlobalNumber(L, "mysqlPort", 3306);
        integer[GAME_PORT] = getGlobalNumber(L, "gameProtocolPort", 7172);
        integer[LOGIN_PORT] = getGlobalNumber(L, "loginProtocolPort", 7171);
        integer[STATUS_PORT] = getGlobalNumber(L, "statusProtocolPort", 7171);

        integer[MARKET_OFFER_DURATION] = getGlobalNumber(L, "marketOfferDuration", 30 * 24 * 60 * 60);
    }

    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[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[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);

    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] = getGlobalNumber(L, "deSpawnRange", 2);
    integer[DEFAULT_DESPAWNRADIUS] = getGlobalNumber(L, "deSpawnRadius", 50);
    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 * 1000);
    integer[WHITE_SKULL_TIME] = getGlobalNumber(L, "whiteSkullTime", 15 * 60 * 1000);
    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);


    // floating loot (added)
    floating[RATE_LOOT] = getGlobalFloat(L, "rateLoot", 2.0);

    loaded = true;
    lua_close(L);
    return true;
}

bool ConfigManager::reload()
{
    bool result = load();
    if (transformToSHA1(getString(ConfigManager::MOTD)) != g_game.getMotdHash()) {
        g_game.incrementMotdNum();
    }
    return result;
}

const std::string& ConfigManager::getString(string_config_t what) const
{
    if (what >= LAST_STRING_CONFIG) {
        std::cout << "[Warning - ConfigManager::getString] Accessing invalid index: " << what << std::endl;
        return string[DUMMY_STR];
    }
    return string[what];
}

int32_t ConfigManager::getNumber(integer_config_t what) const
{
    if (what >= LAST_INTEGER_CONFIG) {
        std::cout << "[Warning - ConfigManager::getNumber] Accessing invalid index: " << what << std::endl;
        return 0;
    }
    return integer[what];
}

bool ConfigManager::getBoolean(boolean_config_t what) const
{
    if (what >= LAST_BOOLEAN_CONFIG) {
        std::cout << "[Warning - ConfigManager::getBoolean] Accessing invalid index: " << what << std::endl;
        return false;
    }
    return boolean[what];
}

std::string ConfigManager::getGlobalString(lua_State* L, const char* identifier, const char* defaultValue)
{
    lua_getglobal(L, identifier);
    if (!lua_isstring(L, -1)) {
        return defaultValue;
    }

    size_t len = lua_strlen(L, -1);
    std::string ret(lua_tostring(L, -1), len);
    lua_pop(L, 1);
    return ret;
}

int32_t ConfigManager::getGlobalNumber(lua_State* L, const char* identifier, const int32_t defaultValue)
{
    lua_getglobal(L, identifier);
    if (!lua_isnumber(L, -1)) {
        return defaultValue;
    }

    int32_t val = lua_tonumber(L, -1);
    lua_pop(L, 1);
    return val;
}

bool ConfigManager::getGlobalBoolean(lua_State* L, const char* identifier, const bool defaultValue)
{
    lua_getglobal(L, identifier);
    if (!lua_isboolean(L, -1)) {
        if (!lua_isstring(L, -1)) {
            return defaultValue;
        }

        size_t len = lua_strlen(L, -1);
        std::string ret(lua_tostring(L, -1), len);
        lua_pop(L, 1);
        return booleanString(ret);
    }

    int val = lua_toboolean(L, -1);
    lua_pop(L, 1);
    return val != 0;
}


// floating loot (added)
float getGlobalFloat(lua_State* L, const char* identifier, const float defaultValue = 0.0)
{
    lua_getglobal(L, identifier);
    if (!lua_isnumber(L, -1)) {
        return defaultValue;

    }

    float val = lua_tonumber(L, -1);
    lua_pop(L, 1);
    return val;
}

// floating loot (added)
float ConfigManager::getFloat(floating_config_t what) const
{
    if (what >= LAST_FLOATING_CONFIG) {
        std::cout << "[Warning - ConfigManager::getFLoat] Accessing invalid index: " << what << std::endl;
        return 0;
      
    }
    return floating[what];
}
 
Last edited:
My code looks a bit different (I think this one in your link is from another tfs version)
I Hope I added a new lines of code in a correct place. I will check if it's work in the moment.

Code:
#include "otpch.h"

#include "configmanager.h"
#include "game.h"

#if LUA_VERSION_NUM >= 502
#undef lua_strlen
#define lua_strlen lua_rawlen
#endif

extern Game g_game;

bool ConfigManager::load()
{
    lua_State* L = luaL_newstate();
    if (!L) {
        throw std::runtime_error("Failed to allocate memory");
    }

    luaL_openlibs(L);

    if (luaL_dofile(L, "config.lua")) {
        std::cout << "[Error - ConfigManager::load] " << lua_tostring(L, -1) << std::endl;
        lua_close(L);
        return false;
    }

    //parse config
    if (!loaded) { //info that must be loaded one time (unless we reset the modules involved)
        boolean[BIND_ONLY_GLOBAL_ADDRESS] = getGlobalBoolean(L, "bindOnlyGlobalAddress", false);
        boolean[OPTIMIZE_DATABASE] = getGlobalBoolean(L, "startupDatabaseOptimization", true);

        string[IP] = getGlobalString(L, "ip", "127.0.0.1");
        string[MAP_NAME] = getGlobalString(L, "mapName", "forgotten");
        string[MAP_AUTHOR] = getGlobalString(L, "mapAuthor", "Unknown");
        string[HOUSE_RENT_PERIOD] = getGlobalString(L, "houseRentPeriod", "never");
        string[MYSQL_HOST] = getGlobalString(L, "mysqlHost", "127.0.0.1");
        string[MYSQL_USER] = getGlobalString(L, "mysqlUser", "forgottenserver");
        string[MYSQL_PASS] = getGlobalString(L, "mysqlPass", "");
        string[MYSQL_DB] = getGlobalString(L, "mysqlDatabase", "forgottenserver");
        string[MYSQL_SOCK] = getGlobalString(L, "mysqlSock", "");

        integer[SQL_PORT] = getGlobalNumber(L, "mysqlPort", 3306);
        integer[GAME_PORT] = getGlobalNumber(L, "gameProtocolPort", 7172);
        integer[LOGIN_PORT] = getGlobalNumber(L, "loginProtocolPort", 7171);
        integer[STATUS_PORT] = getGlobalNumber(L, "statusProtocolPort", 7171);

        integer[MARKET_OFFER_DURATION] = getGlobalNumber(L, "marketOfferDuration", 30 * 24 * 60 * 60);
    }

    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[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[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);

    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] = getGlobalNumber(L, "deSpawnRange", 2);
    integer[DEFAULT_DESPAWNRADIUS] = getGlobalNumber(L, "deSpawnRadius", 50);
    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 * 1000);
    integer[WHITE_SKULL_TIME] = getGlobalNumber(L, "whiteSkullTime", 15 * 60 * 1000);
    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);


    // floating loot (added)
    floating[RATE_LOOT] = getGlobalFloat(L, "rateLoot", 2.0);

    loaded = true;
    lua_close(L);
    return true;
}

bool ConfigManager::reload()
{
    bool result = load();
    if (transformToSHA1(getString(ConfigManager::MOTD)) != g_game.getMotdHash()) {
        g_game.incrementMotdNum();
    }
    return result;
}

const std::string& ConfigManager::getString(string_config_t what) const
{
    if (what >= LAST_STRING_CONFIG) {
        std::cout << "[Warning - ConfigManager::getString] Accessing invalid index: " << what << std::endl;
        return string[DUMMY_STR];
    }
    return string[what];
}

int32_t ConfigManager::getNumber(integer_config_t what) const
{
    if (what >= LAST_INTEGER_CONFIG) {
        std::cout << "[Warning - ConfigManager::getNumber] Accessing invalid index: " << what << std::endl;
        return 0;
    }
    return integer[what];
}

bool ConfigManager::getBoolean(boolean_config_t what) const
{
    if (what >= LAST_BOOLEAN_CONFIG) {
        std::cout << "[Warning - ConfigManager::getBoolean] Accessing invalid index: " << what << std::endl;
        return false;
    }
    return boolean[what];
}

std::string ConfigManager::getGlobalString(lua_State* L, const char* identifier, const char* defaultValue)
{
    lua_getglobal(L, identifier);
    if (!lua_isstring(L, -1)) {
        return defaultValue;
    }

    size_t len = lua_strlen(L, -1);
    std::string ret(lua_tostring(L, -1), len);
    lua_pop(L, 1);
    return ret;
}

int32_t ConfigManager::getGlobalNumber(lua_State* L, const char* identifier, const int32_t defaultValue)
{
    lua_getglobal(L, identifier);
    if (!lua_isnumber(L, -1)) {
        return defaultValue;
    }

    int32_t val = lua_tonumber(L, -1);
    lua_pop(L, 1);
    return val;
}

bool ConfigManager::getGlobalBoolean(lua_State* L, const char* identifier, const bool defaultValue)
{
    lua_getglobal(L, identifier);
    if (!lua_isboolean(L, -1)) {
        if (!lua_isstring(L, -1)) {
            return defaultValue;
        }

        size_t len = lua_strlen(L, -1);
        std::string ret(lua_tostring(L, -1), len);
        lua_pop(L, 1);
        return booleanString(ret);
    }

    int val = lua_toboolean(L, -1);
    lua_pop(L, 1);
    return val != 0;
}


// floating loot (added)
float getGlobalFloat(lua_State* L, const char* identifier, const float defaultValue = 0.0)
{
    lua_getglobal(L, identifier);
    if (!lua_isnumber(L, -1)) {
        return defaultValue;

    }

    float val = lua_tonumber(L, -1);
    lua_pop(L, 1);
    return val;
}

// floating loot (added)
float ConfigManager::getFloat(floating_config_t what) const
{
    if (what >= LAST_FLOATING_CONFIG) {
        std::cout << "[Warning - ConfigManager::getFLoat] Accessing invalid index: " << what << std::endl;
        return 0;
    
    }
    return floating[what];
}
you need float ConfigManager::getGlobalFloat not float getGlobalFloat since you're using older code
 
do you have creature event what executes on monster kill?
Do you have game method to create item?
Do you have container method to put new items in it?

if all yes, then you can make your own loot system which will allow floating numbers.
 
I try so hard to change this code and I have no idea how to do this. My configmanager.cpp is totaly different then this one on github.
Can anyone help me? I will be really grateful :)

My code:
Code:
/**
 * The Forgotten Server - a free and open-source MMORPG server emulator
 * Copyright (C) 2016  Mark Samman <[email protected]>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include "otpch.h"

#include "configmanager.h"
#include "game.h"

#if LUA_VERSION_NUM >= 502
#undef lua_strlen
#define lua_strlen lua_rawlen
#endif

extern Game g_game;

bool ConfigManager::load()
{
    lua_State* L = luaL_newstate();
    if (!L) {
        throw std::runtime_error("Failed to allocate memory");
    }

    luaL_openlibs(L);

    if (luaL_dofile(L, "config.lua")) {
        std::cout << "[Error - ConfigManager::load] " << lua_tostring(L, -1) << std::endl;
        lua_close(L);
        return false;
    }

    //parse config
    if (!loaded) { //info that must be loaded one time (unless we reset the modules involved)
        boolean[BIND_ONLY_GLOBAL_ADDRESS] = getGlobalBoolean(L, "bindOnlyGlobalAddress", false);
        boolean[OPTIMIZE_DATABASE] = getGlobalBoolean(L, "startupDatabaseOptimization", true);

        string[IP] = getGlobalString(L, "ip", "127.0.0.1");
        string[MAP_NAME] = getGlobalString(L, "mapName", "forgotten");
        string[MAP_AUTHOR] = getGlobalString(L, "mapAuthor", "Unknown");
        string[HOUSE_RENT_PERIOD] = getGlobalString(L, "houseRentPeriod", "never");
        string[MYSQL_HOST] = getGlobalString(L, "mysqlHost", "127.0.0.1");
        string[MYSQL_USER] = getGlobalString(L, "mysqlUser", "forgottenserver");
        string[MYSQL_PASS] = getGlobalString(L, "mysqlPass", "");
        string[MYSQL_DB] = getGlobalString(L, "mysqlDatabase", "forgottenserver");
        string[MYSQL_SOCK] = getGlobalString(L, "mysqlSock", "");

        integer[SQL_PORT] = getGlobalNumber(L, "mysqlPort", 3306);
        integer[GAME_PORT] = getGlobalNumber(L, "gameProtocolPort", 7172);
        integer[LOGIN_PORT] = getGlobalNumber(L, "loginProtocolPort", 7171);
        integer[STATUS_PORT] = getGlobalNumber(L, "statusProtocolPort", 7171);

        integer[MARKET_OFFER_DURATION] = getGlobalNumber(L, "marketOfferDuration", 30 * 24 * 60 * 60);
    }

    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[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[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);

    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] = getGlobalNumber(L, "deSpawnRange", 2);
    integer[DEFAULT_DESPAWNRADIUS] = getGlobalNumber(L, "deSpawnRadius", 50);
    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 * 1000);
    integer[WHITE_SKULL_TIME] = getGlobalNumber(L, "whiteSkullTime", 15 * 60 * 1000);
    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);

    loaded = true;
    lua_close(L);
    return true;
}

bool ConfigManager::reload()
{
    bool result = load();
    if (transformToSHA1(getString(ConfigManager::MOTD)) != g_game.getMotdHash()) {
        g_game.incrementMotdNum();
    }
    return result;
}

const std::string& ConfigManager::getString(string_config_t what) const
{
    if (what >= LAST_STRING_CONFIG) {
        std::cout << "[Warning - ConfigManager::getString] Accessing invalid index: " << what << std::endl;
        return string[DUMMY_STR];
    }
    return string[what];
}

int32_t ConfigManager::getNumber(integer_config_t what) const
{
    if (what >= LAST_INTEGER_CONFIG) {
        std::cout << "[Warning - ConfigManager::getNumber] Accessing invalid index: " << what << std::endl;
        return 0;
    }
    return integer[what];
}

bool ConfigManager::getBoolean(boolean_config_t what) const
{
    if (what >= LAST_BOOLEAN_CONFIG) {
        std::cout << "[Warning - ConfigManager::getBoolean] Accessing invalid index: " << what << std::endl;
        return false;
    }
    return boolean[what];
}

std::string ConfigManager::getGlobalString(lua_State* L, const char* identifier, const char* defaultValue)
{
    lua_getglobal(L, identifier);
    if (!lua_isstring(L, -1)) {
        return defaultValue;
    }

    size_t len = lua_strlen(L, -1);
    std::string ret(lua_tostring(L, -1), len);
    lua_pop(L, 1);
    return ret;
}

int32_t ConfigManager::getGlobalNumber(lua_State* L, const char* identifier, const int32_t defaultValue)
{
    lua_getglobal(L, identifier);
    if (!lua_isnumber(L, -1)) {
        return defaultValue;
    }

    int32_t val = lua_tonumber(L, -1);
    lua_pop(L, 1);
    return val;
}

bool ConfigManager::getGlobalBoolean(lua_State* L, const char* identifier, const bool defaultValue)
{
    lua_getglobal(L, identifier);
    if (!lua_isboolean(L, -1)) {
        if (!lua_isstring(L, -1)) {
            return defaultValue;
        }

        size_t len = lua_strlen(L, -1);
        std::string ret(lua_tostring(L, -1), len);
        lua_pop(L, 1);
        return booleanString(ret);
    }

    int val = lua_toboolean(L, -1);
    lua_pop(L, 1);
    return val != 0;
}


My code should looks like:

Floating point loot rate for config.lua · Vulcanx/forgottenserver@ecc7a9f · GitHub
 
I try so hard to change this code and I have no idea how to do this. My configmanager.cpp is totaly different then this one on github.
Can anyone help me? I will be really grateful :)

My code:
Code:
/**
 * The Forgotten Server - a free and open-source MMORPG server emulator
 * Copyright (C) 2016  Mark Samman <[email protected]>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include "otpch.h"

#include "configmanager.h"
#include "game.h"

#if LUA_VERSION_NUM >= 502
#undef lua_strlen
#define lua_strlen lua_rawlen
#endif

extern Game g_game;

bool ConfigManager::load()
{
    lua_State* L = luaL_newstate();
    if (!L) {
        throw std::runtime_error("Failed to allocate memory");
    }

    luaL_openlibs(L);

    if (luaL_dofile(L, "config.lua")) {
        std::cout << "[Error - ConfigManager::load] " << lua_tostring(L, -1) << std::endl;
        lua_close(L);
        return false;
    }

    //parse config
    if (!loaded) { //info that must be loaded one time (unless we reset the modules involved)
        boolean[BIND_ONLY_GLOBAL_ADDRESS] = getGlobalBoolean(L, "bindOnlyGlobalAddress", false);
        boolean[OPTIMIZE_DATABASE] = getGlobalBoolean(L, "startupDatabaseOptimization", true);

        string[IP] = getGlobalString(L, "ip", "127.0.0.1");
        string[MAP_NAME] = getGlobalString(L, "mapName", "forgotten");
        string[MAP_AUTHOR] = getGlobalString(L, "mapAuthor", "Unknown");
        string[HOUSE_RENT_PERIOD] = getGlobalString(L, "houseRentPeriod", "never");
        string[MYSQL_HOST] = getGlobalString(L, "mysqlHost", "127.0.0.1");
        string[MYSQL_USER] = getGlobalString(L, "mysqlUser", "forgottenserver");
        string[MYSQL_PASS] = getGlobalString(L, "mysqlPass", "");
        string[MYSQL_DB] = getGlobalString(L, "mysqlDatabase", "forgottenserver");
        string[MYSQL_SOCK] = getGlobalString(L, "mysqlSock", "");

        integer[SQL_PORT] = getGlobalNumber(L, "mysqlPort", 3306);
        integer[GAME_PORT] = getGlobalNumber(L, "gameProtocolPort", 7172);
        integer[LOGIN_PORT] = getGlobalNumber(L, "loginProtocolPort", 7171);
        integer[STATUS_PORT] = getGlobalNumber(L, "statusProtocolPort", 7171);

        integer[MARKET_OFFER_DURATION] = getGlobalNumber(L, "marketOfferDuration", 30 * 24 * 60 * 60);
    }

    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[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[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);

    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] = getGlobalNumber(L, "deSpawnRange", 2);
    integer[DEFAULT_DESPAWNRADIUS] = getGlobalNumber(L, "deSpawnRadius", 50);
    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 * 1000);
    integer[WHITE_SKULL_TIME] = getGlobalNumber(L, "whiteSkullTime", 15 * 60 * 1000);
    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);

    loaded = true;
    lua_close(L);
    return true;
}

bool ConfigManager::reload()
{
    bool result = load();
    if (transformToSHA1(getString(ConfigManager::MOTD)) != g_game.getMotdHash()) {
        g_game.incrementMotdNum();
    }
    return result;
}

const std::string& ConfigManager::getString(string_config_t what) const
{
    if (what >= LAST_STRING_CONFIG) {
        std::cout << "[Warning - ConfigManager::getString] Accessing invalid index: " << what << std::endl;
        return string[DUMMY_STR];
    }
    return string[what];
}

int32_t ConfigManager::getNumber(integer_config_t what) const
{
    if (what >= LAST_INTEGER_CONFIG) {
        std::cout << "[Warning - ConfigManager::getNumber] Accessing invalid index: " << what << std::endl;
        return 0;
    }
    return integer[what];
}

bool ConfigManager::getBoolean(boolean_config_t what) const
{
    if (what >= LAST_BOOLEAN_CONFIG) {
        std::cout << "[Warning - ConfigManager::getBoolean] Accessing invalid index: " << what << std::endl;
        return false;
    }
    return boolean[what];
}

std::string ConfigManager::getGlobalString(lua_State* L, const char* identifier, const char* defaultValue)
{
    lua_getglobal(L, identifier);
    if (!lua_isstring(L, -1)) {
        return defaultValue;
    }

    size_t len = lua_strlen(L, -1);
    std::string ret(lua_tostring(L, -1), len);
    lua_pop(L, 1);
    return ret;
}

int32_t ConfigManager::getGlobalNumber(lua_State* L, const char* identifier, const int32_t defaultValue)
{
    lua_getglobal(L, identifier);
    if (!lua_isnumber(L, -1)) {
        return defaultValue;
    }

    int32_t val = lua_tonumber(L, -1);
    lua_pop(L, 1);
    return val;
}

bool ConfigManager::getGlobalBoolean(lua_State* L, const char* identifier, const bool defaultValue)
{
    lua_getglobal(L, identifier);
    if (!lua_isboolean(L, -1)) {
        if (!lua_isstring(L, -1)) {
            return defaultValue;
        }

        size_t len = lua_strlen(L, -1);
        std::string ret(lua_tostring(L, -1), len);
        lua_pop(L, 1);
        return booleanString(ret);
    }

    int val = lua_toboolean(L, -1);
    lua_pop(L, 1);
    return val != 0;
}


My code should looks like:

Floating point loot rate for config.lua · Vulcanx/forgottenserver@ecc7a9f · GitHub
just copy/paste the code i had
it shouldn't be that big of a problem, you're trying to adapt the code instead of just taking the code as a whole (which i intended for you to do)
 
I wouldn't ask for help if I didnt try to do this by myself.
I dont have much experience with c++ but I tried to change this code a lot of times in many variations.
I did the same things like in the link you put here. I changed float getGlobalFloat to float ConfigManager::getGlobalFloat by I still have errors in configmanager.cpp when I start compiling.
You may not closely looked at my code but there are many more differences. I think there should be changed something more...
 
Back
Top