Feature Auto Loot [TFS 1.3]

Hitman94

Excellent OT User
Joined
Feb 9, 2009
Messages
54
Reaction score
5
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
 

Hitman94

Excellent OT User
Joined
Feb 9, 2009
Messages
54
Reaction score
5
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:

Hitman94

Excellent OT User
Joined
Feb 9, 2009
Messages
54
Reaction score
5
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
 

jel

Well-Known Member
Joined
Mar 22, 2014
Messages
31
Reaction score
2
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>
 

Hitman94

Excellent OT User
Joined
Feb 9, 2009
Messages
54
Reaction score
5
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
 

Encrypt

New Member
Joined
Jan 30, 2019
Messages
8
Reaction score
0
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);
 
Top