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

Feature Auto Loot [TFS 1.3]

Everything works on OTX server: D only had to clean everything I had underneath


C++:
void MonsterType :: createLoot (Container * corpse)

Now it looks like this

C++:
void MonsterType::createLoot(Container* corpse)
{
    if (g_config.getNumber(ConfigManager::RATE_LOOT) == 0) {
        corpse->startDecaying();
        return;
    }

    Player* owner = g_game.getPlayerByID(corpse->getCorpseOwner());
    std::string autolooted = "";
    if (!owner || owner->getStaminaMinutes() > 840) {
        for (auto it = info.lootItems.rbegin(), end = info.lootItems.rend(); it != end; ++it) {
            auto itemList = createLootItem(*it);
            if (itemList.empty()) {
                continue;
            }

            for (Item* item : itemList) {
                //check containers
                if (Container* container = item->getContainer()) {
                    if (!createLootContainer(container, *it)) {
                        delete container;
                        continue;
                    }
                }




                if (owner && owner->getAutoLootItem(item->getID())){
                    g_game.internalPlayerAddItem(owner, item, true, CONST_SLOT_WHEREEVER);
                    autolooted = autolooted + ", " + item->getNameDescription();
                } else if (g_game.internalAddItem(corpse, item) != RETURNVALUE_NOERROR) {
                    corpse->internalAddThing(item);
                }
            }
        }

        if (owner) {
            std::ostringstream ss;
            std::string lootMsg = corpse->getContentDescription();
            //ss << "Loot of " << nameDescription << ": " << corpse->getContentDescription(); -- change for autoloot system
            if (autolooted != "" && corpse->getContentDescription() == "nothing"){
                lootMsg = autolooted.erase(0,2) + " that was autolooted";
            } else if (autolooted != ""){
                lootMsg = corpse->getContentDescription() + " and " + autolooted.erase(0,2) + " was auto looted";
            }

            ss << "Loot of " << nameDescription << ": " << lootMsg;

            if (owner->getParty()) {
                ss << " by " << owner->getName();
                owner->getParty()->broadcastPartyLoot(ss.str());
            } else {
                owner->sendTextMessage(MESSAGE_LOOT, ss.str());
            }
        }
    } else {
        std::ostringstream ss;
        ss << "Loot of " << nameDescription << ": nothing (due to low stamina)";

        if (owner->getParty()) {
            owner->getParty()->broadcastPartyLoot(ss.str());
        } else {
            owner->sendTextMessage(MESSAGE_LOOT, ss.str());
        }
    }

    corpse->startDecaying();
}

And I can not connect to my old code, the teeth worked which looks like this


C++:
void MonsterType::createLoot(Container* corpse)
{
    if (g_config.getNumber(ConfigManager::RATE_LOOT) == 0) {
        corpse->startDecaying();
        return;
    }

    if (info.isRewardBoss) {
        auto timestamp = time(nullptr);
        Item* rewardContainer = Item::CreateItem(ITEM_REWARD_CONTAINER);
        rewardContainer->setIntAttr(ITEM_ATTRIBUTE_DATE, timestamp);
        corpse->setIntAttr(ITEM_ATTRIBUTE_DATE, timestamp);
        corpse->internalAddThing(rewardContainer);
        corpse->setRewardCorpse();
        corpse->startDecaying();
        return;
    }

    Player* owner = g_game.getPlayerByID(corpse->getCorpseOwner());
    if (!owner || owner->getStaminaMinutes() > 840) {
        bool canRerollLoot = false;

        if (owner) {
            for (int i = 0; i < 3; i++) {
                if (owner->getPreyType(i) == 3 && name == owner->getPreyName(i)) {
                    uint32_t rand = uniform_random(0, 100);
                    if (rand <= owner->getPreyValue(i)) {
                        canRerollLoot = true;
                    }

                    break;
                }
            }
        }

        for (auto it = info.lootItems.rbegin(), end = info.lootItems.rend(); it != end; ++it) {
            auto itemList = createLootItem(*it, canRerollLoot);
            if (itemList.empty()) {
                continue;
            }

            for (Item* item : itemList) {
                //check containers
                if (Container* container = item->getContainer()) {
                    if (!createLootContainer(container, *it)) {
                        delete container;
                        continue;
                    }
                }

                if (g_game.internalAddItem(corpse, item) != RETURNVALUE_NOERROR) {
                    corpse->internalAddThing(item);
                }
            }
        }

        if (owner) {
            std::ostringstream ss;
            if (canRerollLoot) {
                ss << "Loot of " << nameDescription << " [PREY]: " << corpse->getContentDescription();
            } else {
                ss << "Loot of " << nameDescription << ": " << corpse->getContentDescription();
            }

            if (owner->getParty()) {
                owner->getParty()->broadcastPartyLoot(ss.str());
            } else {
                owner->sendTextMessage(MESSAGE_LOOT, ss.str());
            }
        }
    } else {
        std::ostringstream ss;
        ss << "Loot of " << nameDescription << ": nothing (due to low stamina)";

        if (owner->getParty()) {
            owner->getParty()->broadcastPartyLoot(ss.str());
        } else {
            owner->sendTextMessage(MESSAGE_LOOT, ss.str());
        }
    }

    corpse->startDecaying();
}


Maybe someone wants to combine it so that there are no mistakes I can not give thanks in advance


I apologize for the translator
 
I sat down a bit and did it myself, maybe it will be useful to someone

35138

monster.cpp

C++:
void MonsterType::createLoot(Container* corpse)
{
    if (g_config.getNumber(ConfigManager::RATE_LOOT) == 0) {
        corpse->startDecaying();
        return;
    }

    if (info.isRewardBoss) {
        auto timestamp = time(nullptr);
        Item* rewardContainer = Item::CreateItem(ITEM_REWARD_CONTAINER);
        rewardContainer->setIntAttr(ITEM_ATTRIBUTE_DATE, timestamp);
        corpse->setIntAttr(ITEM_ATTRIBUTE_DATE, timestamp);
        corpse->internalAddThing(rewardContainer);
        corpse->setRewardCorpse();
        corpse->startDecaying();
        return;
    }

    Player* owner = g_game.getPlayerByID(corpse->getCorpseOwner());
    //autoloot
    std::string autolooted = "";
    //
    if (!owner || owner->getStaminaMinutes() > 840) {

        bool canRerollLoot = false;

        if (owner) {
            for (int i = 0; i < 3; i++) {
                if (owner->getPreyType(i) == 3 && name == owner->getPreyName(i)) {
                    uint32_t rand = uniform_random(0, 100);
                    if (rand <= owner->getPreyValue(i)) {
                        canRerollLoot = true;
                    }

                    break;
                }
            }
        }

        for (auto it = info.lootItems.rbegin(), end = info.lootItems.rend(); it != end; ++it) {
            auto itemList = createLootItem(*it, canRerollLoot);
            if (itemList.empty()) {
                continue;
            }

            for (Item* item : itemList) {
                //check containers
                if (Container* container = item->getContainer()) {
                    if (!createLootContainer(container, *it)) {
                        delete container;
                        continue;
                    }
                }

                if (g_game.internalAddItem(corpse, item) != RETURNVALUE_NOERROR) {
                    corpse->internalAddThing(item);
                }
            }
        }
        //autoloot
        for (auto it = info.lootItems.rbegin(), end = info.lootItems.rend(); it != end; ++it) {
            auto itemList = createLootItem(*it);
            if (itemList.empty()) {
                continue;
            }

            for (Item* item : itemList) {
                //check containers
                if (Container* container = item->getContainer()) {
                    if (!createLootContainer(container, *it)) {
                        delete container;
                        continue;
                    }
                }

                if (owner && owner->getAutoLootItem(item->getID())){
                    g_game.internalPlayerAddItem(owner, item, true, CONST_SLOT_WHEREEVER);
                    autolooted = autolooted + ", " + item->getNameDescription();
                } else if (g_game.internalAddItem(corpse, item) != RETURNVALUE_NOERROR) {
                    corpse->internalAddThing(item);
                }
            }
        }
        //

        if (owner) {
            std::ostringstream ss;
            //autoloot
            std::string lootMsg = corpse->getContentDescription();
            //ss << "Loot of " << nameDescription << ": " << corpse->getContentDescription(); -- change for autoloot system
            //
            if (canRerollLoot) {
                ss << "Loot of " << nameDescription << " [PREY]: " << corpse->getContentDescription();
            } else {
                ss << "Loot of " << nameDescription << ": " << corpse->getContentDescription();
            }
            //autoloot
            if (autolooted != "" && corpse->getContentDescription() == "nothing"){
                lootMsg = autolooted.erase(0,2) + " that was autolooted";
            } else if (autolooted != ""){
                lootMsg = corpse->getContentDescription() + " and " + autolooted.erase(0,2) + " was auto looted";
            }
           
            ss << "Loot of " << nameDescription << ": " << lootMsg;
            //
           
            if (owner->getParty()) {
            //autoloot
                ss << " by " << owner->getName();
            //
                owner->getParty()->broadcastPartyLoot(ss.str());
            } else {
                owner->sendTextMessage(MESSAGE_LOOT, ss.str());
            }
        }
    } else {
        std::ostringstream ss;
        ss << "Loot of " << nameDescription << ": nothing (due to low stamina)";

        if (owner->getParty()) {
            owner->getParty()->broadcastPartyLoot(ss.str());
        } else {
            owner->sendTextMessage(MESSAGE_LOOT, ss.str());
        }
    }

    corpse->startDecaying();
}
 
Last edited:
Is it possible to convert this script to make the item collect to the assigned backpack?
for example
!add gold coin, bag
!add worms, orange backpack
!add ham, orange bag

35140
 
help with erro?

Lua Script Error: [TalkAction Interface]
data/talkactions/scripts/autoloot.lua:eek:nSay
data/talkactions/scripts/autoloot.lua:3: attempt to call method 'getAutoLootList' (a nil value)
stack traceback:
[C]: in function 'getAutoLootList'
data/talkactions/scripts/autoloot.lua:3: in function <data/talkactions/scripts/autoloot.lua:1>
 
Have you glued the codes to the engine and compiled it? rather he doubts, because if no error during the bathing did not occur then you are doing something wrong
 
Hello Otlanders.

I tried to make a conversion to tfs 0.4 and got a little bit of success. But since nothing is perfect, the system has several errors (on compile).
I would appreciate your help for a decent conversion. I'm starting in the TFS sources and dont have much knowledge of how tfs works 100%.
I know where is:
C++:
if ((result = db.storeQuery(query.str())))
I transform to:
C++:
if ((result = db->storeQuery(query.str())))

where
C++:
    registerMethod("Player", "AddAutoLootItem", LuaScriptInterface::luaPlayerAddAutoLootItem);
    registerMethod("Player", "RemoveAutoLootItem", LuaScriptInterface::luaPlayerRemoveAutoLootItem);
    registerMethod("Player", "GetAutoLootItem", LuaScriptInterface::luaPlayerGetAutoLootItem);
    registerMethod("Player", "GetAutoLootList", LuaScriptInterface::luaPlayerGetAutoLootList);
i tranform to
C++:
    lua_register(m_luaState, "addAutoLootItem", LuaInterface::luaPlayerAddAutoLootItem);
    lua_register(m_luaState, "removeAutoLootItem", LuaInterface::luaPlayerRemoveAutoLootItem);
    lua_register(m_luaState, "getAutoLootItem", LuaInterface::luaPlayerGetAutoLootItem);
    lua_register(m_luaState, "getAutoLootList", LuaInterface::luaPlayerGetAutoLootList);


But the part in the script where the loot occurs itself is totally different from one version to another.
On monsters.cpp are:
C++:
uint16_t Monsters::getLootRandom()
{
    return (uint16_t)std::ceil((double)random_range(0, MAX_LOOTCHANCE) / g_config.getDouble(ConfigManager::RATE_LOOT));
}

void MonsterType::dropLoot(Container* corpse)
{
    Item* tmpItem = NULL;
    for(LootItems::const_iterator it = lootItems.begin(); it != lootItems.end() && !corpse->full(); ++it)
    {
        if((tmpItem = createLoot(*it)))
        {
            if(Container* container = tmpItem->getContainer())
            {
                if(createChildLoot(container, (*it)))
                    if (owner->getAutoLootItem(item->getID())) {
                    g_game.internalPlayerAddItem(owner, item, true, CONST_SLOT_WHEREEVER);
                    autolooted = autolooted + ", " + item->getNameDescription();
                } else if (g_game.internalAddItem(corpse, item) != RETURNVALUE_NOERROR) {
                   corpse->internalAddThing(item);
               }
                else
                    delete container;
            }
            else
                corpse->__internalAddThing(tmpItem);
        }
    }

    corpse->__startDecaying();
    uint32_t ownerId = corpse->getCorpseOwner();
    std::string autolooted = "";
    if(!ownerId)
        return;

    Player* owner = g_game.getPlayerByGuid(ownerId);
    if(!owner)
        return;

    LootMessage_t message = lootMessage;
    if(message == LOOTMSG_IGNORE)
        message = (LootMessage_t)g_config.getNumber(ConfigManager::LOOT_MESSAGE);

    if(message < LOOTMSG_PLAYER)
        return;

    std::stringstream ss;
    std::string lootMsg = corpse->getContentDescription();
    ss << "Loot of " << nameDescription << ": " << lootMsg;
    if (autolooted != "" && corpse->getContentDescription() == "nothing") {
                lootMsg = autolooted.erase(0,2) + " that was auto looted";
            } else if (autolooted != "") {
                lootMsg =  corpse->getContentDescription() + " and " + autolooted.erase(0,2) + " was auto looted.";
            }
    if(owner->getParty() && message > LOOTMSG_PLAYER)
        owner->getParty()->broadcastMessage((MessageClasses)g_config.getNumber(ConfigManager::LOOT_MESSAGE_TYPE), ss.str());
    else if(message == LOOTMSG_PLAYER || message == LOOTMSG_BOTH)
        owner->sendTextMessage((MessageClasses)g_config.getNumber(ConfigManager::LOOT_MESSAGE_TYPE), ss.str());
}

Item* MonsterType::createLoot(const LootBlock& lootBlock)
{
    uint16_t item = lootBlock.ids[0], random = Monsters::getLootRandom();
    if(lootBlock.ids.size() > 1)
        item = lootBlock.ids[random_range((size_t)0, lootBlock.ids.size() - 1)];

    Item* tmpItem = NULL;
    if(Item::items[item].stackable)
    {
        if(random < lootBlock.chance)
            tmpItem = Item::CreateItem(item, (random % lootBlock.count + 1));
    }
    else if(random < lootBlock.chance)
        tmpItem = Item::CreateItem(item, 0);

    if(!tmpItem)
        return NULL;

    if(lootBlock.subType != -1)
        tmpItem->setSubType(lootBlock.subType);

    if(lootBlock.actionId != -1)
        tmpItem->setActionId(lootBlock.actionId, false);

    if(lootBlock.uniqueId != -1)
        tmpItem->setUniqueId(lootBlock.uniqueId);

    if(!lootBlock.text.empty())
        tmpItem->setText(lootBlock.text);

    return tmpItem;
}

bool MonsterType::createChildLoot(Container* parent, const LootBlock& lootBlock)
{
    LootItems::const_iterator it = lootBlock.childLoot.begin();
    if(it == lootBlock.childLoot.end())
        return true;

    Item* tmpItem = NULL;
    for(; it != lootBlock.childLoot.end() && !parent->full(); ++it)
    {
        if((tmpItem = createLoot(*it)))
        {
            if(Container* container = tmpItem->getContainer())
            {
                if(createChildLoot(container, (*it)))
                    parent->__internalAddThing(container);
                else
                    delete container;
            }
            else
                parent->__internalAddThing(tmpItem);
        }
    }

    return !parent->empty();
}

I have another problems too in iologindata.cpp
C++:
//load autoloot list set
query.str(std::string());
query << "SELECT `autoloot_list` FROM `player_autoloot` WHERE `player_id` = " << player->getGUID();
if ((result = db->storeQuery(query.str()))) {
    uint64_t lootlistSize = 0;
    const char* autolootlist = result->getDataStream("autoloot_list", lootlistSize);
    PropStream propStreamList;
    propStreamList.init(autolootlist, lootlistSize);

    int16_t value;
    int16_t item = propStreamList.read<int16_t>(value);
    while (item) {
        player->addAutoLootItem(value);
        item = propStreamList.read<int16_t>(value);
    }
}
Ther part of
C++:
    const char* autolootlist = result->getDataStream("autoloot_list", lootlistSize);
    PropStream propStreamList;
    propStreamList.init(autolootlist, lootlistSize);
 
I sat down a bit and did it myself, maybe it will be useful to someone

View attachment 35138

monster.cpp

C++:
void MonsterType::createLoot(Container* corpse)
{
    if (g_config.getNumber(ConfigManager::RATE_LOOT) == 0) {
        corpse->startDecaying();
        return;
    }

    if (info.isRewardBoss) {
        auto timestamp = time(nullptr);
        Item* rewardContainer = Item::CreateItem(ITEM_REWARD_CONTAINER);
        rewardContainer->setIntAttr(ITEM_ATTRIBUTE_DATE, timestamp);
        corpse->setIntAttr(ITEM_ATTRIBUTE_DATE, timestamp);
        corpse->internalAddThing(rewardContainer);
        corpse->setRewardCorpse();
        corpse->startDecaying();
        return;
    }

    Player* owner = g_game.getPlayerByID(corpse->getCorpseOwner());
    //autoloot
    std::string autolooted = "";
    //
    if (!owner || owner->getStaminaMinutes() > 840) {

        bool canRerollLoot = false;

        if (owner) {
            for (int i = 0; i < 3; i++) {
                if (owner->getPreyType(i) == 3 && name == owner->getPreyName(i)) {
                    uint32_t rand = uniform_random(0, 100);
                    if (rand <= owner->getPreyValue(i)) {
                        canRerollLoot = true;
                    }

                    break;
                }
            }
        }

        for (auto it = info.lootItems.rbegin(), end = info.lootItems.rend(); it != end; ++it) {
            auto itemList = createLootItem(*it, canRerollLoot);
            if (itemList.empty()) {
                continue;
            }

            for (Item* item : itemList) {
                //check containers
                if (Container* container = item->getContainer()) {
                    if (!createLootContainer(container, *it)) {
                        delete container;
                        continue;
                    }
                }

                if (g_game.internalAddItem(corpse, item) != RETURNVALUE_NOERROR) {
                    corpse->internalAddThing(item);
                }
            }
        }
        //autoloot
        for (auto it = info.lootItems.rbegin(), end = info.lootItems.rend(); it != end; ++it) {
            auto itemList = createLootItem(*it);
            if (itemList.empty()) {
                continue;
            }

            for (Item* item : itemList) {
                //check containers
                if (Container* container = item->getContainer()) {
                    if (!createLootContainer(container, *it)) {
                        delete container;
                        continue;
                    }
                }

                if (owner && owner->getAutoLootItem(item->getID())){
                    g_game.internalPlayerAddItem(owner, item, true, CONST_SLOT_WHEREEVER);
                    autolooted = autolooted + ", " + item->getNameDescription();
                } else if (g_game.internalAddItem(corpse, item) != RETURNVALUE_NOERROR) {
                    corpse->internalAddThing(item);
                }
            }
        }
        //

        if (owner) {
            std::ostringstream ss;
            //autoloot
            std::string lootMsg = corpse->getContentDescription();
            //ss << "Loot of " << nameDescription << ": " << corpse->getContentDescription(); -- change for autoloot system
            //
            if (canRerollLoot) {
                ss << "Loot of " << nameDescription << " [PREY]: " << corpse->getContentDescription();
            } else {
                ss << "Loot of " << nameDescription << ": " << corpse->getContentDescription();
            }
            //autoloot
            if (autolooted != "" && corpse->getContentDescription() == "nothing"){
                lootMsg = autolooted.erase(0,2) + " that was autolooted";
            } else if (autolooted != ""){
                lootMsg = corpse->getContentDescription() + " and " + autolooted.erase(0,2) + " was auto looted";
            }
         
            ss << "Loot of " << nameDescription << ": " << lootMsg;
            //
         
            if (owner->getParty()) {
            //autoloot
                ss << " by " << owner->getName();
            //
                owner->getParty()->broadcastPartyLoot(ss.str());
            } else {
                owner->sendTextMessage(MESSAGE_LOOT, ss.str());
            }
        }
    } else {
        std::ostringstream ss;
        ss << "Loot of " << nameDescription << ": nothing (due to low stamina)";

        if (owner->getParty()) {
            owner->getParty()->broadcastPartyLoot(ss.str());
        } else {
            owner->sendTextMessage(MESSAGE_LOOT, ss.str());
        }
    }

    corpse->startDecaying();
}
bump

same here
 
Last edited:
first check clean code

Lua:
void MonsterType::createLoot(Container* corpse)
{
    if (g_config.getNumber(ConfigManager::RATE_LOOT) == 0) {
        corpse->startDecaying();
        return;
    }

    Player* owner = g_game.getPlayerByID(corpse->getCorpseOwner());
    std::string autolooted = "";
    if (!owner || owner->getStaminaMinutes() > 840) {
        for (auto it = info.lootItems.rbegin(), end = info.lootItems.rend(); it != end; ++it) {
            auto itemList = createLootItem(*it);
            if (itemList.empty()) {
                continue;
            }

            for (Item* item : itemList) {
                //check containers
                if (Container* container = item->getContainer()) {
                    if (!createLootContainer(container, *it)) {
                        delete container;
                        continue;
                    }
                }




                if (owner && owner->getAutoLootItem(item->getID())){
                    g_game.internalPlayerAddItem(owner, item, true, CONST_SLOT_WHEREEVER);
                    autolooted = autolooted + ", " + item->getNameDescription();
                } else if (g_game.internalAddItem(corpse, item) != RETURNVALUE_NOERROR) {
                    corpse->internalAddThing(item);
                }
            }
        }

        if (owner) {
            std::ostringstream ss;
            std::string lootMsg = corpse->getContentDescription();
            //ss << "Loot of " << nameDescription << ": " << corpse->getContentDescription(); -- change for autoloot system
            if (autolooted != "" && corpse->getContentDescription() == "nothing"){
                lootMsg = autolooted.erase(0,2) + " that was autolooted";
            } else if (autolooted != ""){
                lootMsg = corpse->getContentDescription() + " and " + autolooted.erase(0,2) + " was auto looted";
            }

            ss << "Loot of " << nameDescription << ": " << lootMsg;

            if (owner->getParty()) {
                ss << " by " << owner->getName();
                owner->getParty()->broadcastPartyLoot(ss.str());
            } else {
                owner->sendTextMessage(MESSAGE_LOOT, ss.str());
            }
        }
    } else {
        std::ostringstream ss;
        ss << "Loot of " << nameDescription << ": nothing (due to low stamina)";

        if (owner->getParty()) {
            owner->getParty()->broadcastPartyLoot(ss.str());
        } else {
            owner->sendTextMessage(MESSAGE_LOOT, ss.str());
        }
    }

    corpse->startDecaying();
}

if compilation working its good your configuration autoolot paste.
If not working you need help paste error compilation

if compilation working, need compile new-old line from to all compatible scripts
Code:
void MonsterType::createLoot(Container* corpse)
ABOWE
to you older line
if - elseif end bla bla bla
 
Last edited:
[ 1%] Building CXX object CMakeFiles/tfs.dir/src/actions.cpp.o
In file included from /home/tfs2/src/game.h:31:0,
from /home/tfs2/src/actions.cpp:26:
/home/tfs2/src/player.h:1189:8: error: ‘set’ in namespace ‘std’ does not name a template type
std::set<uint32_t> autoLootList;
^
CMakeFiles/tfs.dir/build.make:95: recipe for target 'CMakeFiles/tfs.dir/src/actions.cpp.o' failed
make[2]: *** [CMakeFiles/tfs.dir/src/actions.cpp.o] Error 1
CMakeFiles/Makefile2:122: recipe for target 'CMakeFiles/tfs.dir/all' failed
make[1]: *** [CMakeFiles/tfs.dir/all] Error 2
Makefile:76: recipe for target 'all' failed
make: *** [all] Error 2



HOW TO FIX?
 
You are using 1.2 like you mentioned on your last thread? So why are you trying to just copy/paste 1.3 codes/Lua scripts and expect it too work properly?
You should move on to 1.3 or use the scripts/codes which was made for your TFS version to avoid those frequent errors and to have highest stability.
 
Why i cannot find :

In monsters.cpp, before:
Code:
if (!owner || owner->getStaminaMinutes() > 840) {

Help me please :D
 
Back
Top